Introduction

I believe most people know President Donald Trump’s campaign slogan is “Make America Great Again.”, but do you know this slogan was first used during President Ronald Reagan’s 1980 presidential campaign. This slogan is later adopted by President Cliton for his campiagn, though it’s never formly used as a campaign slogan. One slogan, using by 3 presidents from different parties, spanning over 3 decades is an interesting fact to consider.

Inauguration speech, alongside campaign slogan, delievers a president’s political view and ideology. So, in this project, I would like to investigate how presidential speeches change through time and how they reflect different political preferences from two parties (Democrat and Reublican) in historial contexts.

Lengths, emotions, and topics are some important components of a speeach. So I would like to investigate these three aspects using beeswarm plots, sentiment analysis and topic modeling.

Note: Methods used in beeswarm, sentiment analysis and topic modeling are based on Professor Ying Liu’s tutorial on text mining.

https://github.com/TZstatsADS/ADS_Teaching/blob/master/Tutorials/wk2-TextMining/doc/wk2-Tutorial-TextMining.Rmd

# Check and install needed packages
packages.used=c("rvest", "tibble", "qdap", 
                "sentimentr", "gplots", "dplyr",
                "tm", "syuzhet", "factoextra", 
                "beeswarm", "scales", "RColorBrewer",
                "RANN", "tm", "topicmodels", "xlxs", "reshape2")
# check packages that need to be installed.
packages.needed=setdiff(packages.used, 
                        intersect(installed.packages()[,1], 
                                  packages.used))
# install additional packages
if(length(packages.needed)>0){
  install.packages(packages.needed, dependencies = TRUE)
}
Installing package into <U+393C><U+3E31>C:/Users/Wanting/Documents/R/win-library/3.4<U+393C><U+3E32>
(as <U+393C><U+3E31>lib<U+393C><U+3E32> is unspecified)
Warning in install.packages :
  package ‘xlxs’ is not available (for R version 3.4.1)
# library needed packages
library(xlsx)
library(reshape2)
library(dplyr)
library("rvest")
library("tibble")
library("qdap")
library("sentimentr")
library("gplots")
library("tm")
library("syuzhet")
library("factoextra")
library("beeswarm")
library("scales")
library("RColorBrewer")
library("RANN")
library("tm")
library("topicmodels")
source("../lib/plotstacked.R")
source("../lib/speechFuncs.R")
source("../lib/GetOccurence.R")

Note: This notebook was prepared with the following environmental settings.

print(R.version)
               _                           
platform       x86_64-w64-mingw32          
arch           x86_64                      
os             mingw32                     
system         x86_64, mingw32             
status                                     
major          3                           
minor          4.1                         
year           2017                        
month          06                          
day            30                          
svn rev        72865                       
language       R                           
version.string R version 3.4.1 (2017-06-30)
nickname       Single Candle               

Cleaning Data

In this section, I mainly focus on cleaning and combing data. There are three parts in the original data file. “InaugurationDates” is a txt file, contains president names and dates of their inauguration speeches. “InaugurationInfo” is a xlxs file, includes president names, corresponding file name of their speeches, term, party and words of each speech. The third file is a folder which contains all the inaguration speeches.

I first merge the first two dataframes, based on president names and term. Then I read in all the inauguration text files and combine them with the corresponding presidents and their info. Texts are stored in the column “Fulltext”. All the information is stored in the dataframe “speech”.

Note: Harry S. Truman’s speech is missing, so I exclude it from “speech”.

dates <- read.table("../data/InauguationDates.txt", header = TRUE, fill = TRUE, sep = "\t")
info <- read.xlsx("../data/InaugurationInfo.xlsx", 1,header = TRUE, as.is = TRUE)
getwd()
[1] "C:/Users/Wanting/Documents/GitHub/Spring2018-Project1-Wanting-Cui/doc"
dates2 <- melt(dates, id = "PRESIDENT")
dates2$variable <- as.numeric(as.factor(dates2$variable))
del <- which(dates2$value == "")
dates2 <- dates2[-del, ]
# Manually change some presidents' names, to make names identical in two dataframes
dates2$PRESIDENT <- as.character(dates2$PRESIDENT)
info$President <- as.character(info$President)
dates2[8,1] <- toString("Martin van Buren")
dates2[11,1] <- toString("James K. Polk")
dates2[20,1] <- toString("James Garfield")
info[25,1] <- toString("Grover Cleveland")
info[27,1] <- toString("Grover Cleveland")
dates2[which(dates2$PRESIDENT == "Richard M. Nixon"),1] <- "Richard Nixon"
# Merge df based on president and term
speech <- info %>%
  left_join(dates2, by = c("President" = "PRESIDENT")) %>%
  filter(Term == variable)
 speech<- speech%>%
   select("President", "File","Term", "Party", "Words", "value")
colnames(speech)[6] <- "Date"
speech$Date <- as.Date(speech$Date, format = "%m/%d/%Y")
# 
# # Harry S. Truman's speech is missing from the file
speech <- speech[-41, ]
# Combine the correspoinding speech into the df
speech$Fulltext <- NA
combtext <- function(df){
  exp <- paste("../data/InauguralSpeeches/inaug",df[2],"-",df[3],".txt",sep = "")
  return(paste(readLines(exp), collapse = " "))
}
speech$Fulltext <- apply(speech,1,combtext)
write.csv(speech, file = "../output/speech.csv")

Data Exploratory: Overview

In order to investigate how time and political parties influence the contents of speeches, I would like take a general look on some basic information. The first question came to me was how many parties are there? And how many presidents from each party? There are a total of 38 presidents included in this project. 13 of them are Democrats and 17 of them Republicans. The rest of them are before Democrat and Republican are formed, so I exclude them from the proeject.

Second, I want to look at the length of those speeches. So, I divde data based on party and term, and draw the correspoinding boxplots based on word counts. According to the graph, speeches given by Republican presidents tend to be longer than the ones given by Democratic presidents, and with larger variance. Also, The length of presidents’ first term speeches have more variation of that of the second speeches.

speech%>%
  group_by(Party)%>%
  summarise(Count = n_distinct(President))
speech$Words <- as.numeric(as.character(speech$Words))
NAs introduced by coercion
speech.rep.1 <- filter(speech, Term == 1, Party == "Republican")
speech.rep.2 <- filter(speech, Term == 2, Party == "Republican")
speech.dem.1 <- filter(speech, Term == 1, Party == "Democratic")
speech.dem.2 <- filter(speech, Term == 2, Party == "Democratic")
png("../output/boxplot.png")
boxplot(speech.rep.1$Words, speech.rep.2$Words, speech.dem.1$Words, speech.dem.2$Words,
        names = c("Republican Term 1", "Republican Term 2", "Democratic Term 1", "Democratic Term 2"))
dev.off()
null device 
          1 
boxplot(speech.rep.1$Words, speech.rep.2$Words, speech.dem.1$Words, speech.dem.2$Words,
        names = c("Republican Term 1", "Republican Term 2", "Democratic Term 1", "Democratic Term 2"))

Number of Words in a Sentence

A major factor that influences the length of a speech is number of words in each senetences. So, in this section, I want to look into it. Term one seems like an interesting place to start, since it has more variation, and the length of speeches from the two parties is different as well.

I break the fulltext into sentences, using punctuations to detect the end of a sentence. And stored all these information in “sentence.list”.

sentence.list=NULL
# Use punctuations to detect the end of a sentence
for(i in 1:nrow(speech)){
  sentences=sent_detect(speech$Fulltext[i],
                        endmarks = c("?", ".", "!", "|",";"))
  if(length(sentences)>0){
    emotions=get_nrc_sentiment(sentences)
    word.count=word_count(sentences)
    # colnames(emotions)=paste0("emo.", colnames(emotions))
    # in case the word counts are zeros?
    emotions=diag(1/(word.count+0.01))%*%as.matrix(emotions)
    sentence.list=rbind(sentence.list, 
                        cbind(speech[i,-ncol(speech)],
                              sentences=as.character(sentences), 
                              word.count,
                              emotions,
                              sent.id=1:length(sentences)
                              )
    )
  }
}
sentence.list=
  sentence.list%>%
  filter(!is.na(word.count)) 
sentence.list$Date <- as.Date(sentence.list$Date, format = "%m/%d/%Y")

Filter out sentences with no word count.

sentence.list.dem <- filter(sentence.list, Party == "Democratic", Term ==1)
sentence.list.dem$File <- as.factor(as.character(sentence.list.dem$File))
sentence.list.dem <- sentence.list.dem[order(sentence.list.dem$Date), ]
sentence.list.dem$File = factor(sentence.list.dem$File,levels(sentence.list.dem$File)[c(unique(sentence.list.dem$File))])
png("../output/senDem.png")
beeswarm(word.count~File, data = sentence.list.dem,
         horizontal = TRUE,
         pch=16, col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.8, cex.lab=0.8,
         spacing=5/nlevels(sentence.list.dem$File),
         las=2, xlab="Number of words in a sentence.", ylab="",
         main="Democratic"
         )
dev.off()
null device 
          1 
sentence.list.rep <- filter(sentence.list, Party == "Republican", Term == 1)
sentence.list.rep$File <- as.factor(as.character(sentence.list.rep$File))
sentence.list.rep <- sentence.list.rep[order(sentence.list.rep$Date), ]
sentence.list.rep$File = factor(sentence.list.rep$File,levels(sentence.list.rep$File)[c(unique(sentence.list.rep$File))])
png("../output/senRep.png")
beeswarm(word.count~File, data = sentence.list.rep,
         horizontal = TRUE,
         pch=16, col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.8, cex.lab=0.8,
         spacing=5/nlevels(sentence.list.rep$File),
         las=2, xlab="Number of words in a sentence.", ylab="",
         main="Republican"
         )
dev.off()
null device 
          1 

Rearranging presidents into chronological order.

par(mfrow=c(1,2))
beeswarm(word.count~File, data = sentence.list.dem,
         horizontal = TRUE,
         pch=16, col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.8, cex.lab=0.8,
         spacing=5/nlevels(sentence.list.dem$File),
         las=2, xlab="Number of words in a sentence.", ylab="",
         main="Democratic"
         )
beeswarm(word.count~File, data = sentence.list.rep,
         horizontal = TRUE,
         pch=16, col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.8, cex.lab=0.8,
         spacing=5/nlevels(sentence.list.rep$File),
         las=2, xlab="Number of words in a sentence.", ylab="",
         main="Republican"
         )

All the presidents are arranged in chronological order, as Barack Obama is the lastest president who is a democrat, and Andrew Jackson is the first democratic president. Although there is little difference on number of words between Democrats and Republican. One interesting finding is that, presidents in the past usually use longer sentences. However, as time changes, the line for each president changes from a consistent scatter into an alternation between sparse and scattered. This pattern suggests that speech structures of morden presidents are a combination of short and long sentences.

Short Sentences: What did they say?

Now let’s take a closer look at the short sentences. Why short sentences rarely exist in the old days, but become more and more popular in morden days? I define short sentences, as word counts between 3 to 10, because sentences with word count less than three are normally incomplete or with little useful information, such as phrases Mr., Thank you!.

set.seed(123)
# 21st Century
Trump <- sentence.list%>%
  filter(File=="DonaldJTrump", 
         Term == 1, 
         word.count >=3, word.count<=10)%>%
  select(sentences)%>%sample_n(10)
Obama <- sentence.list%>%
  filter(File=="BarackObama",
         Term == 1,
         word.count >=3, word.count<=10)%>%
  select(sentences)%>%sample_n(10)
# 1990s
Clinton <- sentence.list%>%
  filter(File=="WilliamJClinton",
         Term == 1,
         word.count >=3, word.count<=10)%>%
  select(sentences)%>%sample_n(10)
# 1980s
Reagan <- sentence.list%>%
  filter(File=="RonaldReagan",
         Term == 1,
         word.count >=3, word.count<=10)%>%
  select(sentences)%>%sample_n(10)
# 1970s
Nixon <- sentence.list%>%
  filter(File=="RichardNixon",
         Term == 1,
         word.count >=3, word.count<=10)%>%
  select(sentences)%>%sample_n(10)
# 1960s
Kennedy <- sentence.list%>% 
 filter(File=="JohnFKennedy",
         Term == 1,
         word.count >=3, word.count<=10)%>%
  select(sentences)%>%sample_n(10)
# 19th century  
Lincoln <- sentence.list%>% 
 filter(File=="AbrahamLincoln",
         Term == 1,
         word.count >=3, word.count<=10)%>%
  select(sentences)%>%sample_n(10)
# Combine to a dataframe
shortSen <- data.frame(cbind(Trump, Obama, Clinton, Reagan, Nixon, Kennedy, Lincoln))
colnames(shortSen) <- c("Trump", "Obama", "Clinton", "Reagan", "Nixon", "Kennedy", "Lincoln")
write.csv(shortSen, file = "../output/ShortSentences.csv")
shortSen[1:5, ]

From the result one can see that presidents in rencent decades start to adopt strong, concise and slogan-like sentences into their speeches. One great example is President Donald Trump. His campaign slogan is “Make American great again!”. In his inauguration address, there are several phrases, such as “Together, we will make America strong again”, “We will make America wealthy again”, “We will make America safe again”, which share the same paatern as his slogan.

Sentiment Analysis

Apart from the length of the speech, emotions delieved through the speech are also very important. In this section, I would like to do a sentiment comparison between Republican and Democrat.

png(filename = "../output/heatmap.png")
heatmap.2(cor(sentence.list%>%filter(Term ==1)%>%select(anger:trust)), 
          scale = "none", 
          col = bluered(100), , margin=c(6, 6), key=F,
          trace = "none", density.info = "none")
dev.off()
null device 
          1 
heatmap.2(cor(sentence.list%>%filter(Term ==1)%>%select(anger:trust)), 
          scale = "none", 
          col = bluered(100), , margin=c(6, 6), key=F,
          trace = "none", density.info = "none")
par(mfrow = c(2,1))
# emo.means=colMeans(select(sentence.list, anger:trust)>0.01)
emo.means.dem=colMeans(sentence.list%>%filter(Party == "Democratic")%>%select(anger:trust)>0.01)
col.use=c("red2", "darkgoldenrod1", 
            "chartreuse3", "blueviolet",
            "darkgoldenrod2", "dodgerblue3", 
            "darkgoldenrod1", "darkgoldenrod1")
png(filename = "../output/emoDem.png")
barplot(emo.means.dem[order(emo.means.dem)], las=2, col=col.use[order(emo.means.dem)], horiz=T, main="Inaugural Speeches: Democratic")
dev.off()
png 
  2 
emo.means.rep=colMeans(sentence.list%>%filter(Party == "Republican")%>%select(anger:trust)>0.01)
col.use=c("red2", "darkgoldenrod1", 
            "chartreuse3", "blueviolet",
            "darkgoldenrod2", "dodgerblue3", 
            "darkgoldenrod1", "darkgoldenrod1")
png(filename = "../output/emoRep.png")
barplot(emo.means.rep[order(emo.means.rep)], las=2, col=col.use[order(emo.means.rep)], horiz=T, main="Inaugural Speeches: Republican")
dev.off()
png 
  2 

barplot(emo.means.dem[order(emo.means.dem)], las=2, col=col.use[order(emo.means.dem)], horiz=T, main="Inaugural Speeches: Democratic")
barplot(emo.means.rep[order(emo.means.rep)], las=2, col=col.use[order(emo.means.rep)], horiz=T, main="Inaugural Speeches: Republican")

From the heat map, we can see that all the negative emotions are clustered together, and all the positive ones also clustered together.

According the bar plots, positive emotions, expecially trust, dominate inauguration addresses for both parties. In my opinion, inauguration address is a way to convience people that life in the next four years would better under the new lead. So, there is no surprise that trust and anticipation are the main emotions in those speeches.

Topic Modeling

I believe topics are the soul to a speech. So, in this section, let’s look at what are some topics that presidents covered in their speeches.

corpus.list=sentence.list[2:(nrow(sentence.list)-1), ]
sentence.pre=sentence.list$sentences[1:(nrow(sentence.list)-2)]
sentence.post=sentence.list$sentences[3:(nrow(sentence.list)-1)]
corpus.list$snipets=paste(sentence.pre, corpus.list$sentences, sentence.post, sep=" ")
rm.rows=(1:nrow(corpus.list))[corpus.list$sent.id==1]
rm.rows=c(rm.rows, rm.rows-1)
corpus.list=corpus.list[-rm.rows, ]

Text Minnning

Divide dataframes into four parts based on party and time. I used the year of 1900 as a seperation point, because it’s the end of civil war and start of a new century.

docs.rep.pre <- Corpus(VectorSource((corpus.list%>%
                                  filter(Party == "Republican", Date < "1900-01-01")%>%
                                  select(snipets))[,1]))
docs.rep.post <- Corpus(VectorSource((corpus.list%>%
                                  filter(Party == "Republican", Date >= "1900-01-01")%>%
                                  select(snipets))[,1]))
docs.dem.pre <- Corpus(VectorSource((corpus.list%>%
                                  filter(Party == "Democratic", Date < "1900-01-01")%>%
                                  select(snipets))[,1]))
docs.dem.post <- Corpus(VectorSource((corpus.list%>%
                                  filter(Party == "Democratic", Date >= "1900-01-01")%>%
                                  select(snipets))[,1]))
# writeLines(as.character(docs.rep.pre[1]))
# writeLines(as.character(docs.rep.post[1]))
# writeLines(as.character(docs.dem.pre[1]))
# writeLines(as.character(docs.dem.post[1]))
#remove potentially problematic symbols
docs.rep.pre <-tm_map(docs.rep.pre,content_transformer(tolower))
docs.rep.post <-tm_map(docs.rep.post,content_transformer(tolower))
docs.dem.pre <-tm_map(docs.dem.pre,content_transformer(tolower))
docs.dem.post <-tm_map(docs.dem.post,content_transformer(tolower))
#remove punctuation
docs.rep.pre <- tm_map(docs.rep.pre, removePunctuation)
docs.rep.post <- tm_map(docs.rep.post, removePunctuation)
docs.dem.pre <- tm_map(docs.dem.pre, removePunctuation)
docs.dem.post <- tm_map(docs.dem.post, removePunctuation)
#Strip digits
docs.rep.pre <- tm_map(docs.rep.pre, removeNumbers)
docs.rep.post <- tm_map(docs.rep.post, removeNumbers)
docs.dem.pre <- tm_map(docs.dem.pre, removeNumbers)
docs.dem.post <- tm_map(docs.dem.post, removeNumbers)
#remove stopwords
docs.rep.pre <- tm_map(docs.rep.pre, removeWords, stopwords("english"))
docs.rep.post <- tm_map(docs.rep.post, removeWords, stopwords("english"))
docs.dem.pre <- tm_map(docs.dem.pre, removeWords, stopwords("english"))
docs.dem.post <- tm_map(docs.dem.post, removeWords, stopwords("english"))
#remove whitespace
docs.rep.pre <- tm_map(docs.rep.pre, stripWhitespace)
docs.rep.post <- tm_map(docs.rep.post, stripWhitespace)
docs.dem.pre <- tm_map(docs.dem.pre, stripWhitespace)
docs.dem.post <- tm_map(docs.dem.post, stripWhitespace)
#Stem document
docs.rep.pre <- tm_map(docs.rep.pre,stemDocument)
docs.rep.post <- tm_map(docs.rep.post,stemDocument)
docs.dem.pre <- tm_map(docs.dem.pre,stemDocument)
docs.dem.post <- tm_map(docs.dem.post,stemDocument)

Converting into a document term matrix

dtm.rep.pre <- DocumentTermMatrix(docs.rep.pre)
dtm.rep.post <- DocumentTermMatrix(docs.rep.post)
dtm.dem.pre <- DocumentTermMatrix(docs.dem.pre)
dtm.dem.post <- DocumentTermMatrix(docs.dem.post)
#Find the sum of words in each Document
rowTotals.rep.pre <- apply(dtm.rep.pre , 1, sum) 
rowTotals.rep.post <- apply(dtm.rep.post , 1, sum)
rowTotals.dem.pre <- apply(dtm.dem.pre , 1, sum)
rowTotals.dem.post <- apply(dtm.dem.post , 1, sum)
dtm.rep.pre  <- dtm.rep.pre[rowTotals.rep.pre> 0, ]
dtm.rep.post  <- dtm.rep.post[rowTotals.rep.post> 0, ]
dtm.dem.pre  <- dtm.dem.pre[rowTotals.dem.pre> 0, ]
dtm.dem.post  <- dtm.dem.post[rowTotals.dem.post> 0, ]

LDA

Use LDA to find the top 10 terms in each topics

burnin <- 4000
iter <- 2000
thin <- 500
seed <-list(2003,5,63,100001,765)
nstart <- 5
best <- TRUE
#Number of topics
k <- 10
#Run LDA using Gibbs sampling
ldaOut.rep.pre <-LDA(dtm.rep.pre, k, method="Gibbs", control=list(nstart=nstart, 
                                                 seed = seed, best=best,
                                                 burnin = burnin, iter = iter, 
                                                 thin=thin))
ldaOut.rep.post <-LDA(dtm.rep.post, k, method="Gibbs", control=list(nstart=nstart, 
                                                 seed = seed, best=best,
                                                 burnin = burnin, iter = iter, 
                                                 thin=thin))
ldaOut.dem.pre <-LDA(dtm.dem.pre, k, method="Gibbs", control=list(nstart=nstart, 
                                                 seed = seed, best=best,
                                                 burnin = burnin, iter = iter, 
                                                 thin=thin))
ldaOut.dem.post <-LDA(dtm.dem.post, k, method="Gibbs", control=list(nstart=nstart, 
                                                 seed = seed, best=best,
                                                 burnin = burnin, iter = iter, 
                                                 thin=thin))
#write out results
#docs to topics
ldaOut.topics.rep.pre <- as.matrix(topics(ldaOut.rep.pre))
ldaOut.topics.rep.post <- as.matrix(topics(ldaOut.rep.post))
ldaOut.topics.dem.pre <- as.matrix(topics(ldaOut.dem.pre))
ldaOut.topics.dem.post <- as.matrix(topics(ldaOut.dem.post))
#top 10 terms in each topic
ldaOut.terms.rep.pre <- as.matrix(terms(ldaOut.rep.pre,10))
ldaOut.terms.rep.post <- as.matrix(terms(ldaOut.rep.post,10))
ldaOut.terms.dem.pre <- as.matrix(terms(ldaOut.dem.pre,10))
ldaOut.terms.dem.post <- as.matrix(terms(ldaOut.dem.post,10))
write.csv(ldaOut.terms.rep.pre,file=paste("../output/LDAGibbs",k,"TopicsToTermsRepPre.csv"))
write.csv(ldaOut.terms.rep.post,file=paste("../output/LDAGibbs",k,"TopicsToTermsRepPost.csv"))
write.csv(ldaOut.terms.dem.pre,file=paste("../output/LDAGibbs",k,"TopicsToTermsDemPre.csv"))
write.csv(ldaOut.terms.dem.post,file=paste("../output/LDAGibbs",k,"TopicsToTermsDemPost.csv"))
ldaOut.terms.rep.pre
      Topic 1    Topic 2  Topic 3     Topic 4    Topic 5   Topic 6    Topic 7    Topic 8  
 [1,] "nation"   "will"   "state"     "govern"   "upon"    "upon"     "peopl"    "now"    
 [2,] "great"    "shall"  "constitut" "must"     "free"    "peopl"    "great"    "will"   
 [3,] "peac"     "offic"  "union"     "interest" "right"   "congress" "american" "one"    
 [4,] "polici"   "servic" "peopl"     "secur"    "citizen" "public"   "make"     "year"   
 [5,] "question" "purpos" "nation"    "time"     "govern"  "revenu"   "industri" "everi"  
 [6,] "respect"  "execut" "exist"     "without"  "power"   "duti"     "given"    "war"    
 [7,] "world"    "power"  "made"      "present"  "equal"   "condit"   "need"     "section"
 [8,] "countri"  "right"  "territori" "howev"    "may"     "demand"   "men"      "let"    
 [9,] "good"     "enforc" "institut"  "prosper"  "author"  "may"      "protect"  "effect" 
[10,] "foreign"  "faith"  "first"     "valu"     "local"   "alway"    "product"  "hope"   
      Topic 9     Topic 10   
 [1,] "law"       "countri"  
 [2,] "can"       "parti"    
 [3,] "constitut" "unit"     
 [4,] "case"      "subject"  
 [5,] "may"       "administr"
 [6,] "question"  "polit"    
 [7,] "never"     "import"   
 [8,] "person"    "accept"   
 [9,] "provis"    "best"     
[10,] "object"    "civil"    
ldaOut.terms.rep.post
      Topic 1   Topic 2    Topic 3   Topic 4  Topic 5    Topic 6  Topic 7     Topic 8   Topic 9  
 [1,] "time"    "american" "must"    "war"    "state"    "world"  "law"       "freedom" "nation" 
 [2,] "today"   "great"    "govern"  "never"  "may"      "peac"   "busi"      "one"     "upon"   
 [3,] "year"    "life"     "can"     "civil"  "unit"     "new"    "protect"   "hope"    "respons"
 [4,] "now"     "need"     "peopl"   "faith"  "shall"    "let"    "secur"     "peopl"   "great"  
 [5,] "citizen" "mean"     "much"    "caus"   "countri"  "seek"   "congress"  "free"    "among"  
 [6,] "day"     "home"     "continu" "ideal"  "part"     "man"    "feder"     "know"    "power"  
 [7,] "histori" "call"     "public"  "spirit" "maintain" "old"    "administr" "human"   "justic" 
 [8,] "god"     "opportun" "econom"  "common" "increas"  "earth"  "parti"     "can"     "duti"   
 [9,] "countri" "product"  "without" "republ" "direct"   "turn"   "import"    "men"     "way"    
[10,] "mani"    "better"   "effort"  "confid" "condit"   "toward" "execut"    "liberti" "support"
      Topic 10 
 [1,] "will"   
 [2,] "america"
 [3,] "make"   
 [4,] "right"  
 [5,] "work"   
 [6,] "good"   
 [7,] "everi"  
 [8,] "live"   
 [9,] "togeth" 
[10,] "heart"  
ldaOut.terms.dem.pre
      Topic 1    Topic 2    Topic 3  Topic 4     Topic 5    Topic 6   Topic 7   Topic 8   
 [1,] "upon"     "interest" "will"   "state"     "union"    "great"   "countri" "peopl"   
 [2,] "right"    "protect"  "can"    "power"     "institut" "time"    "free"    "public"  
 [3,] "shall"    "one"      "shall"  "constitut" "everi"    "present" "prosper" "govern"  
 [4,] "regard"   "govern"   "good"   "govern"    "exist"    "experi"  "govern"  "citizen" 
 [5,] "opinion"  "equal"    "may"    "unit"      "form"     "danger"  "liberti" "american"
 [6,] "question" "within"   "confid" "feder"     "must"     "patriot" "ever"    "law"     
 [7,] "everi"    "revenu"   "result" "general"   "system"   "spirit"  "bless"   "limit"   
 [8,] "secur"    "home"     "found"  "exercis"   "polit"    "wise"    "wisdom"  "constant"
 [9,] "principl" "duti"     "hope"   "congress"  "domest"   "popul"   "mind"    "promot"  
[10,] "now"      "far"      "expect" "limit"     "object"   "subject" "trade"   "encourag"
      Topic 9         Topic 10   
 [1,] "will"          "nation"   
 [2,] "duti"          "foreign"  
 [3,] "countrymen"    "peac"     
 [4,] "faith"         "territori"
 [5,] "best"          "polici"   
 [6,] "yet"           "extend"   
 [7,] "fellowcitizen" "independ" 
 [8,] "respons"       "well"     
 [9,] "men"           "may"      
[10,] "offic"         "war"      
ldaOut.terms.dem.post
      Topic 1  Topic 2    Topic 3  Topic 4    Topic 5    Topic 6     Topic 7  Topic 8  Topic 9  
 [1,] "now"    "will"     "shall"  "must"     "new"      "nation"    "peopl"  "life"   "govern" 
 [2,] "today"  "can"      "may"    "american" "world"    "â€\u009d"  "power"  "great"  "let"    
 [3,] "day"    "work"     "one"    "time"     "america"  "know"      "make"   "thing"  "without"
 [4,] "year"   "togeth"   "polit"  "chang"    "centuri"  "live"      "nation" "men"    "unit"   
 [5,] "justic" "children" "seek"   "fellow"   "land"     "democraci" "peac"   "come"   "never"  
 [6,] "stand"  "help"     "spirit" "citizen"  "promis"   "see"       "good"   "purpos" "strong" 
 [7,] "god"    "way"      "action" "mean"     "less"     "part"      "right"  "upon"   "nation" 
 [8,] "just"   "act"      "duti"   "liberti"  "old"      "human"     "state"  "use"    "problem"
 [9,] "end"    "better"   "ask"    "endur"    "challeng" "million"   "upon"   "mani"   "forc"   
[10,] "word"   "learn"    "task"   "well"     "respons"  "men"       "equal"  "women"  "side"   
      Topic 10 
 [1,] "everi"  
 [2,] "generat"
 [3,] "freedom"
 [4,] "believ" 
 [5,] "call"   
 [6,] "peopl"  
 [7,] "histori"
 [8,] "common" 
 [9,] "ideal"  
[10,] "long"   

A Closer Look on Specific Topics

Some topics consistently show up in all four subsets, for example: America, nation, law, freedom, right. However, some topics only show up in certain party or time period. In this section, let’s look at two topics: war and world.

The topic war constantly shows up in Reublican speeches, no matter the time period. At first, I was thinking, before 20th century, there was Civil War, and after in the 20th century, there were WWI and WWII, so it’s kind of make sense to have war on a constant topic. However, I realize that the president during WWI was Woodrow Wilson, and the president during WWII was Franklin Roosevelt, in which both of them are Democrats. Only Abraham Lincoln, who was a Republican, was the president during Civil War.

This fact intrigued me, so I looked into their speeches. In Lincoln’s speeches, he mentioned “war” over 10 times, while in Roosevelt’s third term speech he didn’t mention “war” at all, and only once in his fourth inauguration speech.

Another topic that comes to my attention is “world”, which is rarely used before 1900s and becomes widely used post 1900s.

Thus, based on two observations, I decide to count the occurance of certain topics to verify my observations.

docs.rep.pre1 <- tm_map(docs.rep.pre,PlainTextDocument)
docs.rep.post1 <- tm_map(docs.rep.post,PlainTextDocument)
docs.dem.pre1 <- tm_map(docs.dem.pre,PlainTextDocument)
docs.dem.post1 <- tm_map(docs.dem.post,PlainTextDocument)
wrds.rep.pre1 <- strsplit(paste(unlist(docs.rep.pre1), collapse = " "), ' ')[[1]]
wrds.rep.post1 <- strsplit(paste(unlist(docs.rep.post1), collapse = " "), ' ')[[1]]
wrds.dem.pre1 <- strsplit(paste(unlist(docs.dem.pre1), collapse = " "), ' ')[[1]]
wrds.dem.post1 <- strsplit(paste(unlist(docs.dem.post1), collapse = " "), ' ')[[1]]
tblWrds.rep.pre1 <- table(wrds.rep.pre1)
tblWrds.rep.post1 <- table(wrds.rep.post1)
tblWrds.dem.pre1 <- table(wrds.dem.pre1)
tblWrds.dem.post1 <- table(wrds.dem.post1)

The GetOccurence method is based on a stackoverflow post

https://stackoverflow.com/questions/35887730/counting-occurence-of-a-word-in-a-text-file-using-r

war

glob
world

First of all, on the topic war (words include: war, warseek, warfare, wartime), Republicans metioned this topic significant more frequently than Democrats, especially post 1900s. Presidents from Rupublican party have mentioned war for over 158 times, compare with 78 times from the Democrat party.

Second, the topic world or globe is more frequently covered after 1900s for both Republican and Demcrat parties. Before 1900s, the word “world” is only used in total of 101 times, whereas after 1900s, this word is used almost 800 times in total. I think this result coincides with the timeline of globalization. Globalization began in the 1820s, but didn’t gain momentuem until the late 19th century and early 20th century. It only becomes popular in 1970s.

Conclusion

Presidential speeches from both parties and different time periods share lots of similarities. First, all of them deliver positive emotions, such as trust and anticipations. Also, in topic modeling, America, nation, law, freedom, right are some common topics for all addresses.

However, as each presidential address is unqiue, I uncover some differences in their speeches based on time and party differences. First of all, the speech structure changes through time. In the past, speeches are composed by long sentences, while in nowadays in a mixture of short and long. The short sentences have strong tone and concise which is very slogan-like. In addition, from topic modeling,I find that the topic of “world” and “global” didn’t come up until 20th century, which constant the timeline of globalization. Party wise, I observe that the topic “war” is frequently mentioned by Rebulican presidents, but not a lot by Democratic Presidents, which is a good reflection of differeces between parties’ fundemental political views.

LS0tDQp0aXRsZTogIkluYWd1cmF0aW9uIFNwZWVjaCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdA0KICBodG1sX25vdGVib29rOiBkZWZhdWx0DQotLS0NCg0KIyBJbnRyb2R1Y3Rpb24NCkkgYmVsaWV2ZSBtb3N0IHBlb3BsZSBrbm93IFByZXNpZGVudCBEb25hbGQgVHJ1bXAncyBjYW1wYWlnbiBzbG9nYW4gaXMgIk1ha2UgQW1lcmljYSBHcmVhdCBBZ2Fpbi4iLCBidXQgZG8geW91IGtub3cgdGhpcyBzbG9nYW4gd2FzIGZpcnN0IHVzZWQgZHVyaW5nIFByZXNpZGVudCBSb25hbGQgUmVhZ2FuJ3MgMTk4MCBwcmVzaWRlbnRpYWwgY2FtcGFpZ24uIFRoaXMgc2xvZ2FuIGlzIGxhdGVyIGFkb3B0ZWQgYnkgUHJlc2lkZW50IENsaXRvbiBmb3IgaGlzIGNhbXBpYWduLCB0aG91Z2ggaXQncyBuZXZlciBmb3JtbHkgdXNlZCBhcyBhIGNhbXBhaWduIHNsb2dhbi4gT25lIHNsb2dhbiwgdXNpbmcgYnkgMyBwcmVzaWRlbnRzIGZyb20gZGlmZmVyZW50IHBhcnRpZXMsIHNwYW5uaW5nIG92ZXIgMyBkZWNhZGVzIGlzIGFuIGludGVyZXN0aW5nIGZhY3QgdG8gY29uc2lkZXIuDQpcbmV3bGluZQ0KDQpJbmF1Z3VyYXRpb24gc3BlZWNoLCBhbG9uZ3NpZGUgY2FtcGFpZ24gc2xvZ2FuLCBkZWxpZXZlcnMgYSBwcmVzaWRlbnQncyBwb2xpdGljYWwgdmlldyBhbmQgaWRlb2xvZ3kuIFNvLCBpbiB0aGlzIHByb2plY3QsIEkgd291bGQgbGlrZSB0byBpbnZlc3RpZ2F0ZSBob3cgcHJlc2lkZW50aWFsIHNwZWVjaGVzIGNoYW5nZSB0aHJvdWdoIHRpbWUgYW5kIGhvdyB0aGV5IHJlZmxlY3QgZGlmZmVyZW50IHBvbGl0aWNhbCBwcmVmZXJlbmNlcyBmcm9tIHR3byBwYXJ0aWVzIChEZW1vY3JhdCBhbmQgUmV1YmxpY2FuKSBpbiBoaXN0b3JpYWwgY29udGV4dHMuDQpcbmV3bGluZQ0KDQpMZW5ndGhzLCBlbW90aW9ucywgYW5kIHRvcGljcyBhcmUgc29tZSBpbXBvcnRhbnQgY29tcG9uZW50cyBvZiBhIHNwZWVhY2guIFNvIEkgd291bGQgbGlrZSB0byBpbnZlc3RpZ2F0ZSB0aGVzZSB0aHJlZSBhc3BlY3RzIHVzaW5nIGJlZXN3YXJtIHBsb3RzLCBzZW50aW1lbnQgYW5hbHlzaXMgYW5kIHRvcGljIG1vZGVsaW5nLg0KXG5ld2xpbmUNCg0KTm90ZTogTWV0aG9kcyB1c2VkIGluIGJlZXN3YXJtLCBzZW50aW1lbnQgYW5hbHlzaXMgYW5kIHRvcGljIG1vZGVsaW5nIGFyZSBiYXNlZCBvbiBQcm9mZXNzb3IgWWluZyBMaXUncyB0dXRvcmlhbCBvbiB0ZXh0IG1pbmluZy4NClxuZXdsaW5lDQoNCmh0dHBzOi8vZ2l0aHViLmNvbS9UWnN0YXRzQURTL0FEU19UZWFjaGluZy9ibG9iL21hc3Rlci9UdXRvcmlhbHMvd2syLVRleHRNaW5pbmcvZG9jL3drMi1UdXRvcmlhbC1UZXh0TWluaW5nLlJtZA0KDQpgYGB7cn0NCiMgQ2hlY2sgYW5kIGluc3RhbGwgbmVlZGVkIHBhY2thZ2VzDQoNCnBhY2thZ2VzLnVzZWQ9YygicnZlc3QiLCAidGliYmxlIiwgInFkYXAiLCANCiAgICAgICAgICAgICAgICAic2VudGltZW50ciIsICJncGxvdHMiLCAiZHBseXIiLA0KICAgICAgICAgICAgICAgICJ0bSIsICJzeXV6aGV0IiwgImZhY3RvZXh0cmEiLCANCiAgICAgICAgICAgICAgICAiYmVlc3dhcm0iLCAic2NhbGVzIiwgIlJDb2xvckJyZXdlciIsDQogICAgICAgICAgICAgICAgIlJBTk4iLCAidG0iLCAidG9waWNtb2RlbHMiLCAieGx4cyIsICJyZXNoYXBlMiIpDQoNCiMgY2hlY2sgcGFja2FnZXMgdGhhdCBuZWVkIHRvIGJlIGluc3RhbGxlZC4NCnBhY2thZ2VzLm5lZWRlZD1zZXRkaWZmKHBhY2thZ2VzLnVzZWQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJzZWN0KGluc3RhbGxlZC5wYWNrYWdlcygpWywxXSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2FnZXMudXNlZCkpDQojIGluc3RhbGwgYWRkaXRpb25hbCBwYWNrYWdlcw0KaWYobGVuZ3RoKHBhY2thZ2VzLm5lZWRlZCk+MCl7DQogIGluc3RhbGwucGFja2FnZXMocGFja2FnZXMubmVlZGVkLCBkZXBlbmRlbmNpZXMgPSBUUlVFKQ0KfQ0KYGBgDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIGxpYnJhcnkgbmVlZGVkIHBhY2thZ2VzDQoNCmxpYnJhcnkoeGxzeCkNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KGRwbHlyKQ0KDQpsaWJyYXJ5KCJydmVzdCIpDQpsaWJyYXJ5KCJ0aWJibGUiKQ0KbGlicmFyeSgicWRhcCIpDQpsaWJyYXJ5KCJzZW50aW1lbnRyIikNCmxpYnJhcnkoImdwbG90cyIpDQpsaWJyYXJ5KCJ0bSIpDQpsaWJyYXJ5KCJzeXV6aGV0IikNCmxpYnJhcnkoImZhY3RvZXh0cmEiKQ0KbGlicmFyeSgiYmVlc3dhcm0iKQ0KbGlicmFyeSgic2NhbGVzIikNCmxpYnJhcnkoIlJDb2xvckJyZXdlciIpDQpsaWJyYXJ5KCJSQU5OIikNCmxpYnJhcnkoInRtIikNCmxpYnJhcnkoInRvcGljbW9kZWxzIikNCg0Kc291cmNlKCIuLi9saWIvcGxvdHN0YWNrZWQuUiIpDQpzb3VyY2UoIi4uL2xpYi9zcGVlY2hGdW5jcy5SIikNCnNvdXJjZSgiLi4vbGliL0dldE9jY3VyZW5jZS5SIikNCmBgYA0KDQpOb3RlOiBUaGlzIG5vdGVib29rIHdhcyBwcmVwYXJlZCB3aXRoIHRoZSBmb2xsb3dpbmcgZW52aXJvbm1lbnRhbCBzZXR0aW5ncy4NCg0KYGBge3J9DQpwcmludChSLnZlcnNpb24pDQpgYGANCg0KIyBDbGVhbmluZyBEYXRhDQpJbiB0aGlzIHNlY3Rpb24sIEkgbWFpbmx5IGZvY3VzIG9uIGNsZWFuaW5nIGFuZCBjb21iaW5nIGRhdGEuIFRoZXJlIGFyZSB0aHJlZSBwYXJ0cyBpbiB0aGUgb3JpZ2luYWwgZGF0YSBmaWxlLiAiSW5hdWd1cmF0aW9uRGF0ZXMiIGlzIGEgdHh0IGZpbGUsIGNvbnRhaW5zIHByZXNpZGVudCBuYW1lcyBhbmQgZGF0ZXMgb2YgdGhlaXIgaW5hdWd1cmF0aW9uIHNwZWVjaGVzLiAiSW5hdWd1cmF0aW9uSW5mbyIgaXMgYSB4bHhzIGZpbGUsIGluY2x1ZGVzIHByZXNpZGVudCBuYW1lcywgY29ycmVzcG9uZGluZyBmaWxlIG5hbWUgb2YgdGhlaXIgc3BlZWNoZXMsIHRlcm0sIHBhcnR5IGFuZCB3b3JkcyBvZiBlYWNoIHNwZWVjaC4gVGhlIHRoaXJkIGZpbGUgaXMgYSBmb2xkZXIgd2hpY2ggY29udGFpbnMgYWxsIHRoZSBpbmFndXJhdGlvbiBzcGVlY2hlcy4gDQpcbmV3bGluZQ0KDQpJIGZpcnN0IG1lcmdlIHRoZSBmaXJzdCB0d28gZGF0YWZyYW1lcywgYmFzZWQgb24gcHJlc2lkZW50IG5hbWVzIGFuZCB0ZXJtLiBUaGVuIEkgcmVhZCBpbiBhbGwgdGhlIGluYXVndXJhdGlvbiB0ZXh0IGZpbGVzIGFuZCBjb21iaW5lIHRoZW0gd2l0aCB0aGUgY29ycmVzcG9uZGluZyBwcmVzaWRlbnRzIGFuZCB0aGVpciBpbmZvLiBUZXh0cyBhcmUgc3RvcmVkIGluIHRoZSBjb2x1bW4gIkZ1bGx0ZXh0Ii4gQWxsIHRoZSBpbmZvcm1hdGlvbiBpcyBzdG9yZWQgaW4gdGhlIGRhdGFmcmFtZSAic3BlZWNoIi4NClxuZXdsaW5lDQoNCk5vdGU6IEhhcnJ5IFMuIFRydW1hbidzIHNwZWVjaCBpcyBtaXNzaW5nLCBzbyBJIGV4Y2x1ZGUgaXQgZnJvbSAic3BlZWNoIi4NClxuZXdsaW5lDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpkYXRlcyA8LSByZWFkLnRhYmxlKCIuLi9kYXRhL0luYXVndWF0aW9uRGF0ZXMudHh0IiwgaGVhZGVyID0gVFJVRSwgZmlsbCA9IFRSVUUsIHNlcCA9ICJcdCIpDQppbmZvIDwtIHJlYWQueGxzeCgiLi4vZGF0YS9JbmF1Z3VyYXRpb25JbmZvLnhsc3giLCAxLGhlYWRlciA9IFRSVUUsIGFzLmlzID0gVFJVRSkNCmdldHdkKCkNCg0KZGF0ZXMyIDwtIG1lbHQoZGF0ZXMsIGlkID0gIlBSRVNJREVOVCIpDQpkYXRlczIkdmFyaWFibGUgPC0gYXMubnVtZXJpYyhhcy5mYWN0b3IoZGF0ZXMyJHZhcmlhYmxlKSkNCmRlbCA8LSB3aGljaChkYXRlczIkdmFsdWUgPT0gIiIpDQpkYXRlczIgPC0gZGF0ZXMyWy1kZWwsIF0NCg0KIyBNYW51YWxseSBjaGFuZ2Ugc29tZSBwcmVzaWRlbnRzJyBuYW1lcywgdG8gbWFrZSBuYW1lcyBpZGVudGljYWwgaW4gdHdvIGRhdGFmcmFtZXMNCmRhdGVzMiRQUkVTSURFTlQgPC0gYXMuY2hhcmFjdGVyKGRhdGVzMiRQUkVTSURFTlQpDQppbmZvJFByZXNpZGVudCA8LSBhcy5jaGFyYWN0ZXIoaW5mbyRQcmVzaWRlbnQpDQpkYXRlczJbOCwxXSA8LSB0b1N0cmluZygiTWFydGluIHZhbiBCdXJlbiIpDQpkYXRlczJbMTEsMV0gPC0gdG9TdHJpbmcoIkphbWVzIEsuIFBvbGsiKQ0KZGF0ZXMyWzIwLDFdIDwtIHRvU3RyaW5nKCJKYW1lcyBHYXJmaWVsZCIpDQppbmZvWzI1LDFdIDwtIHRvU3RyaW5nKCJHcm92ZXIgQ2xldmVsYW5kIikNCmluZm9bMjcsMV0gPC0gdG9TdHJpbmcoIkdyb3ZlciBDbGV2ZWxhbmQiKQ0KZGF0ZXMyW3doaWNoKGRhdGVzMiRQUkVTSURFTlQgPT0gIlJpY2hhcmQgTS4gTml4b24iKSwxXSA8LSAiUmljaGFyZCBOaXhvbiINCg0KIyBNZXJnZSBkZiBiYXNlZCBvbiBwcmVzaWRlbnQgYW5kIHRlcm0NCnNwZWVjaCA8LSBpbmZvICU+JQ0KICBsZWZ0X2pvaW4oZGF0ZXMyLCBieSA9IGMoIlByZXNpZGVudCIgPSAiUFJFU0lERU5UIikpICU+JQ0KICBmaWx0ZXIoVGVybSA9PSB2YXJpYWJsZSkNCiBzcGVlY2g8LSBzcGVlY2glPiUNCiAgIHNlbGVjdCgiUHJlc2lkZW50IiwgIkZpbGUiLCJUZXJtIiwgIlBhcnR5IiwgIldvcmRzIiwgInZhbHVlIikNCmNvbG5hbWVzKHNwZWVjaClbNl0gPC0gIkRhdGUiDQpzcGVlY2gkRGF0ZSA8LSBhcy5EYXRlKHNwZWVjaCREYXRlLCBmb3JtYXQgPSAiJW0vJWQvJVkiKQ0KIyANCiMgIyBIYXJyeSBTLiBUcnVtYW4ncyBzcGVlY2ggaXMgbWlzc2luZyBmcm9tIHRoZSBmaWxlDQpzcGVlY2ggPC0gc3BlZWNoWy00MSwgXQ0KYGBgDQoNCmBgYHtyLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIENvbWJpbmUgdGhlIGNvcnJlc3BvaW5kaW5nIHNwZWVjaCBpbnRvIHRoZSBkZg0Kc3BlZWNoJEZ1bGx0ZXh0IDwtIE5BDQpjb21idGV4dCA8LSBmdW5jdGlvbihkZil7DQogIGV4cCA8LSBwYXN0ZSgiLi4vZGF0YS9JbmF1Z3VyYWxTcGVlY2hlcy9pbmF1ZyIsZGZbMl0sIi0iLGRmWzNdLCIudHh0IixzZXAgPSAiIikNCiAgcmV0dXJuKHBhc3RlKHJlYWRMaW5lcyhleHApLCBjb2xsYXBzZSA9ICIgIikpDQp9DQoNCnNwZWVjaCRGdWxsdGV4dCA8LSBhcHBseShzcGVlY2gsMSxjb21idGV4dCkNCg0Kd3JpdGUuY3N2KHNwZWVjaCwgZmlsZSA9ICIuLi9vdXRwdXQvc3BlZWNoLmNzdiIpDQpgYGANCg0KDQojIERhdGEgRXhwbG9yYXRvcnk6IE92ZXJ2aWV3DQoNCkluIG9yZGVyIHRvIGludmVzdGlnYXRlIGhvdyB0aW1lIGFuZCBwb2xpdGljYWwgcGFydGllcyBpbmZsdWVuY2UgdGhlIGNvbnRlbnRzIG9mIHNwZWVjaGVzLCBJIHdvdWxkIGxpa2UgdGFrZSBhIGdlbmVyYWwgbG9vayBvbiBzb21lIGJhc2ljIGluZm9ybWF0aW9uLiBUaGUgZmlyc3QgcXVlc3Rpb24gY2FtZSB0byBtZSB3YXMgaG93IG1hbnkgcGFydGllcyBhcmUgdGhlcmU/IEFuZCBob3cgbWFueSBwcmVzaWRlbnRzIGZyb20gZWFjaCBwYXJ0eT8gVGhlcmUgYXJlIGEgdG90YWwgb2YgMzggcHJlc2lkZW50cyBpbmNsdWRlZCBpbiB0aGlzIHByb2plY3QuIDEzIG9mIHRoZW0gYXJlIERlbW9jcmF0cyBhbmQgMTcgb2YgdGhlbSBSZXB1YmxpY2Fucy4gVGhlIHJlc3Qgb2YgdGhlbSBhcmUgYmVmb3JlIERlbW9jcmF0IGFuZCBSZXB1YmxpY2FuIGFyZSBmb3JtZWQsIHNvIEkgZXhjbHVkZSB0aGVtIGZyb20gdGhlIHByb2VqZWN0Lg0KXG5ld2xpbmUNCg0KU2Vjb25kLCBJIHdhbnQgdG8gbG9vayBhdCB0aGUgbGVuZ3RoIG9mIHRob3NlIHNwZWVjaGVzLiBTbywgSSBkaXZkZSBkYXRhIGJhc2VkIG9uIHBhcnR5IGFuZCB0ZXJtLCBhbmQgZHJhdyB0aGUgY29ycmVzcG9pbmRpbmcgYm94cGxvdHMgYmFzZWQgb24gd29yZCBjb3VudHMuIEFjY29yZGluZyB0byB0aGUgZ3JhcGgsIHNwZWVjaGVzIGdpdmVuIGJ5IFJlcHVibGljYW4gcHJlc2lkZW50cyB0ZW5kIHRvIGJlIGxvbmdlciB0aGFuIHRoZSBvbmVzIGdpdmVuIGJ5IERlbW9jcmF0aWMgcHJlc2lkZW50cywgYW5kIHdpdGggbGFyZ2VyIHZhcmlhbmNlLiBBbHNvLCBUaGUgbGVuZ3RoIG9mIHByZXNpZGVudHMnIGZpcnN0IHRlcm0gc3BlZWNoZXMgaGF2ZSBtb3JlIHZhcmlhdGlvbiBvZiB0aGF0IG9mIHRoZSBzZWNvbmQgc3BlZWNoZXMuIA0KDQpgYGB7cn0NCnNwZWVjaCU+JQ0KICBncm91cF9ieShQYXJ0eSklPiUNCiAgc3VtbWFyaXNlKENvdW50ID0gbl9kaXN0aW5jdChQcmVzaWRlbnQpKQ0Kc3BlZWNoJFdvcmRzIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHNwZWVjaCRXb3JkcykpDQpzcGVlY2gucmVwLjEgPC0gZmlsdGVyKHNwZWVjaCwgVGVybSA9PSAxLCBQYXJ0eSA9PSAiUmVwdWJsaWNhbiIpDQpzcGVlY2gucmVwLjIgPC0gZmlsdGVyKHNwZWVjaCwgVGVybSA9PSAyLCBQYXJ0eSA9PSAiUmVwdWJsaWNhbiIpDQpzcGVlY2guZGVtLjEgPC0gZmlsdGVyKHNwZWVjaCwgVGVybSA9PSAxLCBQYXJ0eSA9PSAiRGVtb2NyYXRpYyIpDQpzcGVlY2guZGVtLjIgPC0gZmlsdGVyKHNwZWVjaCwgVGVybSA9PSAyLCBQYXJ0eSA9PSAiRGVtb2NyYXRpYyIpDQoNCnBuZygiLi4vb3V0cHV0L2JveHBsb3QucG5nIikNCmJveHBsb3Qoc3BlZWNoLnJlcC4xJFdvcmRzLCBzcGVlY2gucmVwLjIkV29yZHMsIHNwZWVjaC5kZW0uMSRXb3Jkcywgc3BlZWNoLmRlbS4yJFdvcmRzLA0KICAgICAgICBuYW1lcyA9IGMoIlJlcHVibGljYW4gVGVybSAxIiwgIlJlcHVibGljYW4gVGVybSAyIiwgIkRlbW9jcmF0aWMgVGVybSAxIiwgIkRlbW9jcmF0aWMgVGVybSAyIikpDQpkZXYub2ZmKCkNCg0KYm94cGxvdChzcGVlY2gucmVwLjEkV29yZHMsIHNwZWVjaC5yZXAuMiRXb3Jkcywgc3BlZWNoLmRlbS4xJFdvcmRzLCBzcGVlY2guZGVtLjIkV29yZHMsDQogICAgICAgIG5hbWVzID0gYygiUmVwdWJsaWNhbiBUZXJtIDEiLCAiUmVwdWJsaWNhbiBUZXJtIDIiLCAiRGVtb2NyYXRpYyBUZXJtIDEiLCAiRGVtb2NyYXRpYyBUZXJtIDIiKSkNCmBgYA0KDQojIyBOdW1iZXIgb2YgV29yZHMgaW4gYSBTZW50ZW5jZQ0KQSBtYWpvciBmYWN0b3IgdGhhdCBpbmZsdWVuY2VzIHRoZSBsZW5ndGggb2YgYSBzcGVlY2ggaXMgbnVtYmVyIG9mIHdvcmRzIGluIGVhY2ggc2VuZXRlbmNlcy4gU28sIGluIHRoaXMgc2VjdGlvbiwgSSB3YW50IHRvIGxvb2sgaW50byBpdC4gVGVybSBvbmUgc2VlbXMgbGlrZSBhbiBpbnRlcmVzdGluZyBwbGFjZSB0byBzdGFydCwgc2luY2UgaXQgaGFzIG1vcmUgdmFyaWF0aW9uLCBhbmQgdGhlIGxlbmd0aCBvZiBzcGVlY2hlcyBmcm9tIHRoZSB0d28gcGFydGllcyBpcyBkaWZmZXJlbnQgYXMgd2VsbC4gDQpcbmV3bGluZQ0KDQpJIGJyZWFrIHRoZSBmdWxsdGV4dCBpbnRvIHNlbnRlbmNlcywgdXNpbmcgcHVuY3R1YXRpb25zIHRvIGRldGVjdCB0aGUgZW5kIG9mIGEgc2VudGVuY2UuIEFuZCBzdG9yZWQgYWxsIHRoZXNlIGluZm9ybWF0aW9uIGluICJzZW50ZW5jZS5saXN0Ii4NCmBgYHtyLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpzZW50ZW5jZS5saXN0PU5VTEwNCg0KIyBVc2UgcHVuY3R1YXRpb25zIHRvIGRldGVjdCB0aGUgZW5kIG9mIGEgc2VudGVuY2UNCmZvcihpIGluIDE6bnJvdyhzcGVlY2gpKXsNCiAgc2VudGVuY2VzPXNlbnRfZGV0ZWN0KHNwZWVjaCRGdWxsdGV4dFtpXSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGVuZG1hcmtzID0gYygiPyIsICIuIiwgIiEiLCAifCIsIjsiKSkNCiAgaWYobGVuZ3RoKHNlbnRlbmNlcyk+MCl7DQogICAgZW1vdGlvbnM9Z2V0X25yY19zZW50aW1lbnQoc2VudGVuY2VzKQ0KICAgIHdvcmQuY291bnQ9d29yZF9jb3VudChzZW50ZW5jZXMpDQogICAgIyBjb2xuYW1lcyhlbW90aW9ucyk9cGFzdGUwKCJlbW8uIiwgY29sbmFtZXMoZW1vdGlvbnMpKQ0KICAgICMgaW4gY2FzZSB0aGUgd29yZCBjb3VudHMgYXJlIHplcm9zPw0KICAgIGVtb3Rpb25zPWRpYWcoMS8od29yZC5jb3VudCswLjAxKSklKiVhcy5tYXRyaXgoZW1vdGlvbnMpDQogICAgc2VudGVuY2UubGlzdD1yYmluZChzZW50ZW5jZS5saXN0LCANCiAgICAgICAgICAgICAgICAgICAgICAgIGNiaW5kKHNwZWVjaFtpLC1uY29sKHNwZWVjaCldLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VudGVuY2VzPWFzLmNoYXJhY3RlcihzZW50ZW5jZXMpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmQuY291bnQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbW90aW9ucywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbnQuaWQ9MTpsZW5ndGgoc2VudGVuY2VzKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KICAgICkNCiAgfQ0KfQ0KYGBgDQoNCg0KYGBge3J9DQoNCnNlbnRlbmNlLmxpc3Q9DQogIHNlbnRlbmNlLmxpc3QlPiUNCiAgZmlsdGVyKCFpcy5uYSh3b3JkLmNvdW50KSkgDQoNCnNlbnRlbmNlLmxpc3QkRGF0ZSA8LSBhcy5EYXRlKHNlbnRlbmNlLmxpc3QkRGF0ZSwgZm9ybWF0ID0gIiVtLyVkLyVZIikNCmBgYA0KRmlsdGVyIG91dCBzZW50ZW5jZXMgd2l0aCBubyB3b3JkIGNvdW50Lg0KDQpgYGB7cn0NCg0Kc2VudGVuY2UubGlzdC5kZW0gPC0gZmlsdGVyKHNlbnRlbmNlLmxpc3QsIFBhcnR5ID09ICJEZW1vY3JhdGljIiwgVGVybSA9PTEpDQpzZW50ZW5jZS5saXN0LmRlbSRGaWxlIDwtIGFzLmZhY3Rvcihhcy5jaGFyYWN0ZXIoc2VudGVuY2UubGlzdC5kZW0kRmlsZSkpDQpzZW50ZW5jZS5saXN0LmRlbSA8LSBzZW50ZW5jZS5saXN0LmRlbVtvcmRlcihzZW50ZW5jZS5saXN0LmRlbSREYXRlKSwgXQ0Kc2VudGVuY2UubGlzdC5kZW0kRmlsZSA9IGZhY3RvcihzZW50ZW5jZS5saXN0LmRlbSRGaWxlLGxldmVscyhzZW50ZW5jZS5saXN0LmRlbSRGaWxlKVtjKHVuaXF1ZShzZW50ZW5jZS5saXN0LmRlbSRGaWxlKSldKQ0KcG5nKCIuLi9vdXRwdXQvc2VuRGVtLnBuZyIpDQpiZWVzd2FybSh3b3JkLmNvdW50fkZpbGUsIGRhdGEgPSBzZW50ZW5jZS5saXN0LmRlbSwNCiAgICAgICAgIGhvcml6b250YWwgPSBUUlVFLA0KICAgICAgICAgcGNoPTE2LCBjb2w9YWxwaGEoYnJld2VyLnBhbCg5LCAiU2V0MSIpLCAwLjYpLCANCiAgICAgICAgIGNleD0wLjU1LCBjZXguYXhpcz0wLjgsIGNleC5sYWI9MC44LA0KICAgICAgICAgc3BhY2luZz01L25sZXZlbHMoc2VudGVuY2UubGlzdC5kZW0kRmlsZSksDQogICAgICAgICBsYXM9MiwgeGxhYj0iTnVtYmVyIG9mIHdvcmRzIGluIGEgc2VudGVuY2UuIiwgeWxhYj0iIiwNCiAgICAgICAgIG1haW49IkRlbW9jcmF0aWMiDQogICAgICAgICApDQpkZXYub2ZmKCkNCg0Kc2VudGVuY2UubGlzdC5yZXAgPC0gZmlsdGVyKHNlbnRlbmNlLmxpc3QsIFBhcnR5ID09ICJSZXB1YmxpY2FuIiwgVGVybSA9PSAxKQ0Kc2VudGVuY2UubGlzdC5yZXAkRmlsZSA8LSBhcy5mYWN0b3IoYXMuY2hhcmFjdGVyKHNlbnRlbmNlLmxpc3QucmVwJEZpbGUpKQ0Kc2VudGVuY2UubGlzdC5yZXAgPC0gc2VudGVuY2UubGlzdC5yZXBbb3JkZXIoc2VudGVuY2UubGlzdC5yZXAkRGF0ZSksIF0NCnNlbnRlbmNlLmxpc3QucmVwJEZpbGUgPSBmYWN0b3Ioc2VudGVuY2UubGlzdC5yZXAkRmlsZSxsZXZlbHMoc2VudGVuY2UubGlzdC5yZXAkRmlsZSlbYyh1bmlxdWUoc2VudGVuY2UubGlzdC5yZXAkRmlsZSkpXSkNCnBuZygiLi4vb3V0cHV0L3NlblJlcC5wbmciKQ0KYmVlc3dhcm0od29yZC5jb3VudH5GaWxlLCBkYXRhID0gc2VudGVuY2UubGlzdC5yZXAsDQogICAgICAgICBob3Jpem9udGFsID0gVFJVRSwNCiAgICAgICAgIHBjaD0xNiwgY29sPWFscGhhKGJyZXdlci5wYWwoOSwgIlNldDEiKSwgMC42KSwgDQogICAgICAgICBjZXg9MC41NSwgY2V4LmF4aXM9MC44LCBjZXgubGFiPTAuOCwNCiAgICAgICAgIHNwYWNpbmc9NS9ubGV2ZWxzKHNlbnRlbmNlLmxpc3QucmVwJEZpbGUpLA0KICAgICAgICAgbGFzPTIsIHhsYWI9Ik51bWJlciBvZiB3b3JkcyBpbiBhIHNlbnRlbmNlLiIsIHlsYWI9IiIsDQogICAgICAgICBtYWluPSJSZXB1YmxpY2FuIg0KICAgICAgICAgKQ0KZGV2Lm9mZigpDQpgYGANClJlYXJyYW5naW5nIHByZXNpZGVudHMgaW50byBjaHJvbm9sb2dpY2FsIG9yZGVyLg0KDQpgYGB7cn0NCnBhcihtZnJvdz1jKDEsMikpDQpiZWVzd2FybSh3b3JkLmNvdW50fkZpbGUsIGRhdGEgPSBzZW50ZW5jZS5saXN0LmRlbSwNCiAgICAgICAgIGhvcml6b250YWwgPSBUUlVFLA0KICAgICAgICAgcGNoPTE2LCBjb2w9YWxwaGEoYnJld2VyLnBhbCg5LCAiU2V0MSIpLCAwLjYpLCANCiAgICAgICAgIGNleD0wLjU1LCBjZXguYXhpcz0wLjgsIGNleC5sYWI9MC44LA0KICAgICAgICAgc3BhY2luZz01L25sZXZlbHMoc2VudGVuY2UubGlzdC5kZW0kRmlsZSksDQogICAgICAgICBsYXM9MiwgeGxhYj0iTnVtYmVyIG9mIHdvcmRzIGluIGEgc2VudGVuY2UuIiwgeWxhYj0iIiwNCiAgICAgICAgIG1haW49IkRlbW9jcmF0aWMiDQogICAgICAgICApDQpiZWVzd2FybSh3b3JkLmNvdW50fkZpbGUsIGRhdGEgPSBzZW50ZW5jZS5saXN0LnJlcCwNCiAgICAgICAgIGhvcml6b250YWwgPSBUUlVFLA0KICAgICAgICAgcGNoPTE2LCBjb2w9YWxwaGEoYnJld2VyLnBhbCg5LCAiU2V0MSIpLCAwLjYpLCANCiAgICAgICAgIGNleD0wLjU1LCBjZXguYXhpcz0wLjgsIGNleC5sYWI9MC44LA0KICAgICAgICAgc3BhY2luZz01L25sZXZlbHMoc2VudGVuY2UubGlzdC5yZXAkRmlsZSksDQogICAgICAgICBsYXM9MiwgeGxhYj0iTnVtYmVyIG9mIHdvcmRzIGluIGEgc2VudGVuY2UuIiwgeWxhYj0iIiwNCiAgICAgICAgIG1haW49IlJlcHVibGljYW4iDQogICAgICAgICApDQpgYGANClxuZXdsaW5lDQoNCkFsbCB0aGUgcHJlc2lkZW50cyBhcmUgYXJyYW5nZWQgaW4gY2hyb25vbG9naWNhbCBvcmRlciwgYXMgQmFyYWNrIE9iYW1hIGlzIHRoZSBsYXN0ZXN0IHByZXNpZGVudCB3aG8gaXMgYSBkZW1vY3JhdCwgYW5kIEFuZHJldyBKYWNrc29uIGlzIHRoZSBmaXJzdCBkZW1vY3JhdGljIHByZXNpZGVudC4gQWx0aG91Z2ggdGhlcmUgaXMgbGl0dGxlIGRpZmZlcmVuY2Ugb24gbnVtYmVyIG9mIHdvcmRzIGJldHdlZW4gRGVtb2NyYXRzIGFuZCBSZXB1YmxpY2FuLiBPbmUgaW50ZXJlc3RpbmcgZmluZGluZyBpcyB0aGF0LCBwcmVzaWRlbnRzIGluIHRoZSBwYXN0IHVzdWFsbHkgdXNlIGxvbmdlciBzZW50ZW5jZXMuIEhvd2V2ZXIsIGFzIHRpbWUgY2hhbmdlcywgdGhlIGxpbmUgZm9yIGVhY2ggcHJlc2lkZW50IGNoYW5nZXMgZnJvbSBhIGNvbnNpc3RlbnQgc2NhdHRlciBpbnRvIGFuIGFsdGVybmF0aW9uIGJldHdlZW4gc3BhcnNlIGFuZCBzY2F0dGVyZWQuIFRoaXMgcGF0dGVybiBzdWdnZXN0cyB0aGF0IHNwZWVjaCBzdHJ1Y3R1cmVzIG9mIG1vcmRlbiBwcmVzaWRlbnRzIGFyZSBhIGNvbWJpbmF0aW9uIG9mIHNob3J0IGFuZCBsb25nIHNlbnRlbmNlcy4gDQoNCiMgU2hvcnQgU2VudGVuY2VzOiBXaGF0IGRpZCB0aGV5IHNheT8NCk5vdyBsZXQncyB0YWtlIGEgY2xvc2VyIGxvb2sgYXQgdGhlIHNob3J0IHNlbnRlbmNlcy4gV2h5IHNob3J0IHNlbnRlbmNlcyByYXJlbHkgZXhpc3QgaW4gdGhlIG9sZCBkYXlzLCBidXQgYmVjb21lIG1vcmUgYW5kIG1vcmUgcG9wdWxhciBpbiBtb3JkZW4gZGF5cz8gSSBkZWZpbmUgc2hvcnQgc2VudGVuY2VzLCBhcyB3b3JkIGNvdW50cyBiZXR3ZWVuIDMgdG8gMTAsIGJlY2F1c2Ugc2VudGVuY2VzIHdpdGggd29yZCBjb3VudCBsZXNzIHRoYW4gdGhyZWUgYXJlIG5vcm1hbGx5IGluY29tcGxldGUgb3Igd2l0aCBsaXR0bGUgdXNlZnVsIGluZm9ybWF0aW9uLCBzdWNoIGFzIHBocmFzZXMgTXIuLCBUaGFuayB5b3UhLg0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMykNCiMgMjFzdCBDZW50dXJ5DQpUcnVtcCA8LSBzZW50ZW5jZS5saXN0JT4lDQogIGZpbHRlcihGaWxlPT0iRG9uYWxkSlRydW1wIiwgDQogICAgICAgICBUZXJtID09IDEsIA0KICAgICAgICAgd29yZC5jb3VudCA+PTMsIHdvcmQuY291bnQ8PTEwKSU+JQ0KICBzZWxlY3Qoc2VudGVuY2VzKSU+JXNhbXBsZV9uKDEwKQ0KDQpPYmFtYSA8LSBzZW50ZW5jZS5saXN0JT4lDQogIGZpbHRlcihGaWxlPT0iQmFyYWNrT2JhbWEiLA0KICAgICAgICAgVGVybSA9PSAxLA0KICAgICAgICAgd29yZC5jb3VudCA+PTMsIHdvcmQuY291bnQ8PTEwKSU+JQ0KICBzZWxlY3Qoc2VudGVuY2VzKSU+JXNhbXBsZV9uKDEwKQ0KDQojIDE5OTBzDQpDbGludG9uIDwtIHNlbnRlbmNlLmxpc3QlPiUNCiAgZmlsdGVyKEZpbGU9PSJXaWxsaWFtSkNsaW50b24iLA0KICAgICAgICAgVGVybSA9PSAxLA0KICAgICAgICAgd29yZC5jb3VudCA+PTMsIHdvcmQuY291bnQ8PTEwKSU+JQ0KICBzZWxlY3Qoc2VudGVuY2VzKSU+JXNhbXBsZV9uKDEwKQ0KDQojIDE5ODBzDQpSZWFnYW4gPC0gc2VudGVuY2UubGlzdCU+JQ0KICBmaWx0ZXIoRmlsZT09IlJvbmFsZFJlYWdhbiIsDQogICAgICAgICBUZXJtID09IDEsDQogICAgICAgICB3b3JkLmNvdW50ID49Mywgd29yZC5jb3VudDw9MTApJT4lDQogIHNlbGVjdChzZW50ZW5jZXMpJT4lc2FtcGxlX24oMTApDQoNCiMgMTk3MHMNCk5peG9uIDwtIHNlbnRlbmNlLmxpc3QlPiUNCiAgZmlsdGVyKEZpbGU9PSJSaWNoYXJkTml4b24iLA0KICAgICAgICAgVGVybSA9PSAxLA0KICAgICAgICAgd29yZC5jb3VudCA+PTMsIHdvcmQuY291bnQ8PTEwKSU+JQ0KICBzZWxlY3Qoc2VudGVuY2VzKSU+JXNhbXBsZV9uKDEwKQ0KDQojIDE5NjBzDQpLZW5uZWR5IDwtIHNlbnRlbmNlLmxpc3QlPiUgDQogZmlsdGVyKEZpbGU9PSJKb2huRktlbm5lZHkiLA0KICAgICAgICAgVGVybSA9PSAxLA0KICAgICAgICAgd29yZC5jb3VudCA+PTMsIHdvcmQuY291bnQ8PTEwKSU+JQ0KICBzZWxlY3Qoc2VudGVuY2VzKSU+JXNhbXBsZV9uKDEwKQ0KDQojIDE5dGggY2VudHVyeSAgDQpMaW5jb2xuIDwtIHNlbnRlbmNlLmxpc3QlPiUgDQogZmlsdGVyKEZpbGU9PSJBYnJhaGFtTGluY29sbiIsDQogICAgICAgICBUZXJtID09IDEsDQogICAgICAgICB3b3JkLmNvdW50ID49Mywgd29yZC5jb3VudDw9MTApJT4lDQogIHNlbGVjdChzZW50ZW5jZXMpJT4lc2FtcGxlX24oMTApDQoNCiMgQ29tYmluZSB0byBhIGRhdGFmcmFtZQ0Kc2hvcnRTZW4gPC0gZGF0YS5mcmFtZShjYmluZChUcnVtcCwgT2JhbWEsIENsaW50b24sIFJlYWdhbiwgTml4b24sIEtlbm5lZHksIExpbmNvbG4pKQ0KY29sbmFtZXMoc2hvcnRTZW4pIDwtIGMoIlRydW1wIiwgIk9iYW1hIiwgIkNsaW50b24iLCAiUmVhZ2FuIiwgIk5peG9uIiwgIktlbm5lZHkiLCAiTGluY29sbiIpDQp3cml0ZS5jc3Yoc2hvcnRTZW4sIGZpbGUgPSAiLi4vb3V0cHV0L1Nob3J0U2VudGVuY2VzLmNzdiIpDQoNCnNob3J0U2VuWzE6NSwgXQ0KYGBgDQpGcm9tIHRoZSByZXN1bHQgb25lIGNhbiBzZWUgdGhhdCBwcmVzaWRlbnRzIGluIHJlbmNlbnQgZGVjYWRlcyBzdGFydCB0byBhZG9wdCBzdHJvbmcsIGNvbmNpc2UgYW5kIHNsb2dhbi1saWtlIHNlbnRlbmNlcyBpbnRvIHRoZWlyIHNwZWVjaGVzLiBPbmUgZ3JlYXQgZXhhbXBsZSBpcyBQcmVzaWRlbnQgRG9uYWxkIFRydW1wLiBIaXMgY2FtcGFpZ24gc2xvZ2FuIGlzICJNYWtlIEFtZXJpY2FuIGdyZWF0IGFnYWluISIuIEluIGhpcyBpbmF1Z3VyYXRpb24gYWRkcmVzcywgdGhlcmUgYXJlIHNldmVyYWwgcGhyYXNlcywgc3VjaCBhcyAiVG9nZXRoZXIsIHdlIHdpbGwgbWFrZSBBbWVyaWNhIHN0cm9uZyBhZ2FpbiIsICJXZSB3aWxsIG1ha2UgQW1lcmljYSB3ZWFsdGh5IGFnYWluIiwgIldlIHdpbGwgbWFrZSBBbWVyaWNhIHNhZmUgYWdhaW4iLCB3aGljaCBzaGFyZSB0aGUgc2FtZSBwYWF0ZXJuIGFzIGhpcyBzbG9nYW4uIA0KDQojIFNlbnRpbWVudCBBbmFseXNpcw0KQXBhcnQgZnJvbSB0aGUgbGVuZ3RoIG9mIHRoZSBzcGVlY2gsIGVtb3Rpb25zIGRlbGlldmVkIHRocm91Z2ggdGhlIHNwZWVjaCBhcmUgYWxzbyB2ZXJ5IGltcG9ydGFudC4gSW4gdGhpcyBzZWN0aW9uLCBJIHdvdWxkIGxpa2UgdG8gZG8gYSBzZW50aW1lbnQgY29tcGFyaXNvbiBiZXR3ZWVuIFJlcHVibGljYW4gYW5kIERlbW9jcmF0Lg0KDQpgYGB7cn0NCnBuZyhmaWxlbmFtZSA9ICIuLi9vdXRwdXQvaGVhdG1hcC5wbmciKQ0KaGVhdG1hcC4yKGNvcihzZW50ZW5jZS5saXN0JT4lZmlsdGVyKFRlcm0gPT0xKSU+JXNlbGVjdChhbmdlcjp0cnVzdCkpLCANCiAgICAgICAgICBzY2FsZSA9ICJub25lIiwgDQogICAgICAgICAgY29sID0gYmx1ZXJlZCgxMDApLCAsIG1hcmdpbj1jKDYsIDYpLCBrZXk9RiwNCiAgICAgICAgICB0cmFjZSA9ICJub25lIiwgZGVuc2l0eS5pbmZvID0gIm5vbmUiKQ0KZGV2Lm9mZigpDQoNCmhlYXRtYXAuMihjb3Ioc2VudGVuY2UubGlzdCU+JWZpbHRlcihUZXJtID09MSklPiVzZWxlY3QoYW5nZXI6dHJ1c3QpKSwgDQogICAgICAgICAgc2NhbGUgPSAibm9uZSIsIA0KICAgICAgICAgIGNvbCA9IGJsdWVyZWQoMTAwKSwgLCBtYXJnaW49Yyg2LCA2KSwga2V5PUYsDQogICAgICAgICAgdHJhY2UgPSAibm9uZSIsIGRlbnNpdHkuaW5mbyA9ICJub25lIikNCg0KcGFyKG1mcm93ID0gYygyLDEpKQ0KIyBlbW8ubWVhbnM9Y29sTWVhbnMoc2VsZWN0KHNlbnRlbmNlLmxpc3QsIGFuZ2VyOnRydXN0KT4wLjAxKQ0KZW1vLm1lYW5zLmRlbT1jb2xNZWFucyhzZW50ZW5jZS5saXN0JT4lZmlsdGVyKFBhcnR5ID09ICJEZW1vY3JhdGljIiklPiVzZWxlY3QoYW5nZXI6dHJ1c3QpPjAuMDEpDQpjb2wudXNlPWMoInJlZDIiLCAiZGFya2dvbGRlbnJvZDEiLCANCiAgICAgICAgICAgICJjaGFydHJldXNlMyIsICJibHVldmlvbGV0IiwNCiAgICAgICAgICAgICJkYXJrZ29sZGVucm9kMiIsICJkb2RnZXJibHVlMyIsIA0KICAgICAgICAgICAgImRhcmtnb2xkZW5yb2QxIiwgImRhcmtnb2xkZW5yb2QxIikNCnBuZyhmaWxlbmFtZSA9ICIuLi9vdXRwdXQvZW1vRGVtLnBuZyIpDQpiYXJwbG90KGVtby5tZWFucy5kZW1bb3JkZXIoZW1vLm1lYW5zLmRlbSldLCBsYXM9MiwgY29sPWNvbC51c2Vbb3JkZXIoZW1vLm1lYW5zLmRlbSldLCBob3Jpej1ULCBtYWluPSJJbmF1Z3VyYWwgU3BlZWNoZXM6IERlbW9jcmF0aWMiKQ0KZGV2Lm9mZigpDQoNCmVtby5tZWFucy5yZXA9Y29sTWVhbnMoc2VudGVuY2UubGlzdCU+JWZpbHRlcihQYXJ0eSA9PSAiUmVwdWJsaWNhbiIpJT4lc2VsZWN0KGFuZ2VyOnRydXN0KT4wLjAxKQ0KY29sLnVzZT1jKCJyZWQyIiwgImRhcmtnb2xkZW5yb2QxIiwgDQogICAgICAgICAgICAiY2hhcnRyZXVzZTMiLCAiYmx1ZXZpb2xldCIsDQogICAgICAgICAgICAiZGFya2dvbGRlbnJvZDIiLCAiZG9kZ2VyYmx1ZTMiLCANCiAgICAgICAgICAgICJkYXJrZ29sZGVucm9kMSIsICJkYXJrZ29sZGVucm9kMSIpDQpwbmcoZmlsZW5hbWUgPSAiLi4vb3V0cHV0L2Vtb1JlcC5wbmciKQ0KYmFycGxvdChlbW8ubWVhbnMucmVwW29yZGVyKGVtby5tZWFucy5yZXApXSwgbGFzPTIsIGNvbD1jb2wudXNlW29yZGVyKGVtby5tZWFucy5yZXApXSwgaG9yaXo9VCwgbWFpbj0iSW5hdWd1cmFsIFNwZWVjaGVzOiBSZXB1YmxpY2FuIikNCmRldi5vZmYoKQ0KDQpiYXJwbG90KGVtby5tZWFucy5kZW1bb3JkZXIoZW1vLm1lYW5zLmRlbSldLCBsYXM9MiwgY29sPWNvbC51c2Vbb3JkZXIoZW1vLm1lYW5zLmRlbSldLCBob3Jpej1ULCBtYWluPSJJbmF1Z3VyYWwgU3BlZWNoZXM6IERlbW9jcmF0aWMiKQ0KYmFycGxvdChlbW8ubWVhbnMucmVwW29yZGVyKGVtby5tZWFucy5yZXApXSwgbGFzPTIsIGNvbD1jb2wudXNlW29yZGVyKGVtby5tZWFucy5yZXApXSwgaG9yaXo9VCwgbWFpbj0iSW5hdWd1cmFsIFNwZWVjaGVzOiBSZXB1YmxpY2FuIikNCmBgYA0KXG5ld2xpbmUNCg0KRnJvbSB0aGUgaGVhdCBtYXAsIHdlIGNhbiBzZWUgdGhhdCBhbGwgdGhlIG5lZ2F0aXZlIGVtb3Rpb25zIGFyZSBjbHVzdGVyZWQgdG9nZXRoZXIsIGFuZCBhbGwgdGhlIHBvc2l0aXZlIG9uZXMgYWxzbyBjbHVzdGVyZWQgdG9nZXRoZXIuDQpcbmV3bGluZQ0KDQpBY2NvcmRpbmcgdGhlIGJhciBwbG90cywgcG9zaXRpdmUgZW1vdGlvbnMsIGV4cGVjaWFsbHkgdHJ1c3QsIGRvbWluYXRlIGluYXVndXJhdGlvbiBhZGRyZXNzZXMgZm9yIGJvdGggcGFydGllcy4gSW4gbXkgb3BpbmlvbiwgaW5hdWd1cmF0aW9uIGFkZHJlc3MgaXMgYSB3YXkgdG8gY29udmllbmNlIHBlb3BsZSB0aGF0IGxpZmUgaW4gdGhlIG5leHQgZm91ciB5ZWFycyB3b3VsZCBiZXR0ZXIgdW5kZXIgdGhlIG5ldyBsZWFkLiBTbywgdGhlcmUgaXMgbm8gc3VycHJpc2UgdGhhdCB0cnVzdCBhbmQgYW50aWNpcGF0aW9uIGFyZSB0aGUgbWFpbiBlbW90aW9ucyBpbiB0aG9zZSBzcGVlY2hlcy4NCg0KIyBUb3BpYyBNb2RlbGluZw0KSSBiZWxpZXZlIHRvcGljcyBhcmUgdGhlIHNvdWwgdG8gYSBzcGVlY2guIFNvLCBpbiB0aGlzIHNlY3Rpb24sIGxldCdzIGxvb2sgYXQgd2hhdCBhcmUgc29tZSB0b3BpY3MgdGhhdCBwcmVzaWRlbnRzIGNvdmVyZWQgaW4gdGhlaXIgc3BlZWNoZXMuIA0KYGBge3J9DQpjb3JwdXMubGlzdD1zZW50ZW5jZS5saXN0WzI6KG5yb3coc2VudGVuY2UubGlzdCktMSksIF0NCnNlbnRlbmNlLnByZT1zZW50ZW5jZS5saXN0JHNlbnRlbmNlc1sxOihucm93KHNlbnRlbmNlLmxpc3QpLTIpXQ0Kc2VudGVuY2UucG9zdD1zZW50ZW5jZS5saXN0JHNlbnRlbmNlc1szOihucm93KHNlbnRlbmNlLmxpc3QpLTEpXQ0KY29ycHVzLmxpc3Qkc25pcGV0cz1wYXN0ZShzZW50ZW5jZS5wcmUsIGNvcnB1cy5saXN0JHNlbnRlbmNlcywgc2VudGVuY2UucG9zdCwgc2VwPSIgIikNCnJtLnJvd3M9KDE6bnJvdyhjb3JwdXMubGlzdCkpW2NvcnB1cy5saXN0JHNlbnQuaWQ9PTFdDQpybS5yb3dzPWMocm0ucm93cywgcm0ucm93cy0xKQ0KY29ycHVzLmxpc3Q9Y29ycHVzLmxpc3RbLXJtLnJvd3MsIF0NCmBgYA0KDQojIyBUZXh0IE1pbm5uaW5nDQpEaXZpZGUgZGF0YWZyYW1lcyBpbnRvIGZvdXIgcGFydHMgYmFzZWQgb24gcGFydHkgYW5kIHRpbWUuIEkgdXNlZCB0aGUgeWVhciBvZiAxOTAwIGFzIGEgc2VwZXJhdGlvbiBwb2ludCwgYmVjYXVzZSBpdCdzIHRoZSBlbmQgb2YgY2l2aWwgd2FyIGFuZCBzdGFydCBvZiBhIG5ldyBjZW50dXJ5Lg0KDQpgYGB7cn0NCmRvY3MucmVwLnByZSA8LSBDb3JwdXMoVmVjdG9yU291cmNlKChjb3JwdXMubGlzdCU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihQYXJ0eSA9PSAiUmVwdWJsaWNhbiIsIERhdGUgPCAiMTkwMC0wMS0wMSIpJT4lDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0KHNuaXBldHMpKVssMV0pKQ0KZG9jcy5yZXAucG9zdCA8LSBDb3JwdXMoVmVjdG9yU291cmNlKChjb3JwdXMubGlzdCU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihQYXJ0eSA9PSAiUmVwdWJsaWNhbiIsIERhdGUgPj0gIjE5MDAtMDEtMDEiKSU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdChzbmlwZXRzKSlbLDFdKSkNCmRvY3MuZGVtLnByZSA8LSBDb3JwdXMoVmVjdG9yU291cmNlKChjb3JwdXMubGlzdCU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihQYXJ0eSA9PSAiRGVtb2NyYXRpYyIsIERhdGUgPCAiMTkwMC0wMS0wMSIpJT4lDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0KHNuaXBldHMpKVssMV0pKQ0KZG9jcy5kZW0ucG9zdCA8LSBDb3JwdXMoVmVjdG9yU291cmNlKChjb3JwdXMubGlzdCU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihQYXJ0eSA9PSAiRGVtb2NyYXRpYyIsIERhdGUgPj0gIjE5MDAtMDEtMDEiKSU+JQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdChzbmlwZXRzKSlbLDFdKSkNCg0KIyB3cml0ZUxpbmVzKGFzLmNoYXJhY3Rlcihkb2NzLnJlcC5wcmVbMV0pKQ0KIyB3cml0ZUxpbmVzKGFzLmNoYXJhY3Rlcihkb2NzLnJlcC5wb3N0WzFdKSkNCiMgd3JpdGVMaW5lcyhhcy5jaGFyYWN0ZXIoZG9jcy5kZW0ucHJlWzFdKSkNCiMgd3JpdGVMaW5lcyhhcy5jaGFyYWN0ZXIoZG9jcy5kZW0ucG9zdFsxXSkpDQoNCiNyZW1vdmUgcG90ZW50aWFsbHkgcHJvYmxlbWF0aWMgc3ltYm9scw0KZG9jcy5yZXAucHJlIDwtdG1fbWFwKGRvY3MucmVwLnByZSxjb250ZW50X3RyYW5zZm9ybWVyKHRvbG93ZXIpKQ0KZG9jcy5yZXAucG9zdCA8LXRtX21hcChkb2NzLnJlcC5wb3N0LGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpDQpkb2NzLmRlbS5wcmUgPC10bV9tYXAoZG9jcy5kZW0ucHJlLGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpDQpkb2NzLmRlbS5wb3N0IDwtdG1fbWFwKGRvY3MuZGVtLnBvc3QsY29udGVudF90cmFuc2Zvcm1lcih0b2xvd2VyKSkNCg0KI3JlbW92ZSBwdW5jdHVhdGlvbg0KZG9jcy5yZXAucHJlIDwtIHRtX21hcChkb2NzLnJlcC5wcmUsIHJlbW92ZVB1bmN0dWF0aW9uKQ0KZG9jcy5yZXAucG9zdCA8LSB0bV9tYXAoZG9jcy5yZXAucG9zdCwgcmVtb3ZlUHVuY3R1YXRpb24pDQpkb2NzLmRlbS5wcmUgPC0gdG1fbWFwKGRvY3MuZGVtLnByZSwgcmVtb3ZlUHVuY3R1YXRpb24pDQpkb2NzLmRlbS5wb3N0IDwtIHRtX21hcChkb2NzLmRlbS5wb3N0LCByZW1vdmVQdW5jdHVhdGlvbikNCg0KI1N0cmlwIGRpZ2l0cw0KZG9jcy5yZXAucHJlIDwtIHRtX21hcChkb2NzLnJlcC5wcmUsIHJlbW92ZU51bWJlcnMpDQpkb2NzLnJlcC5wb3N0IDwtIHRtX21hcChkb2NzLnJlcC5wb3N0LCByZW1vdmVOdW1iZXJzKQ0KZG9jcy5kZW0ucHJlIDwtIHRtX21hcChkb2NzLmRlbS5wcmUsIHJlbW92ZU51bWJlcnMpDQpkb2NzLmRlbS5wb3N0IDwtIHRtX21hcChkb2NzLmRlbS5wb3N0LCByZW1vdmVOdW1iZXJzKQ0KDQojcmVtb3ZlIHN0b3B3b3Jkcw0KZG9jcy5yZXAucHJlIDwtIHRtX21hcChkb2NzLnJlcC5wcmUsIHJlbW92ZVdvcmRzLCBzdG9wd29yZHMoImVuZ2xpc2giKSkNCmRvY3MucmVwLnBvc3QgPC0gdG1fbWFwKGRvY3MucmVwLnBvc3QsIHJlbW92ZVdvcmRzLCBzdG9wd29yZHMoImVuZ2xpc2giKSkNCmRvY3MuZGVtLnByZSA8LSB0bV9tYXAoZG9jcy5kZW0ucHJlLCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbmdsaXNoIikpDQpkb2NzLmRlbS5wb3N0IDwtIHRtX21hcChkb2NzLmRlbS5wb3N0LCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbmdsaXNoIikpDQoNCiNyZW1vdmUgd2hpdGVzcGFjZQ0KZG9jcy5yZXAucHJlIDwtIHRtX21hcChkb2NzLnJlcC5wcmUsIHN0cmlwV2hpdGVzcGFjZSkNCmRvY3MucmVwLnBvc3QgPC0gdG1fbWFwKGRvY3MucmVwLnBvc3QsIHN0cmlwV2hpdGVzcGFjZSkNCmRvY3MuZGVtLnByZSA8LSB0bV9tYXAoZG9jcy5kZW0ucHJlLCBzdHJpcFdoaXRlc3BhY2UpDQpkb2NzLmRlbS5wb3N0IDwtIHRtX21hcChkb2NzLmRlbS5wb3N0LCBzdHJpcFdoaXRlc3BhY2UpDQoNCiNTdGVtIGRvY3VtZW50DQpkb2NzLnJlcC5wcmUgPC0gdG1fbWFwKGRvY3MucmVwLnByZSxzdGVtRG9jdW1lbnQpDQpkb2NzLnJlcC5wb3N0IDwtIHRtX21hcChkb2NzLnJlcC5wb3N0LHN0ZW1Eb2N1bWVudCkNCmRvY3MuZGVtLnByZSA8LSB0bV9tYXAoZG9jcy5kZW0ucHJlLHN0ZW1Eb2N1bWVudCkNCmRvY3MuZGVtLnBvc3QgPC0gdG1fbWFwKGRvY3MuZGVtLnBvc3Qsc3RlbURvY3VtZW50KQ0KYGBgDQoNCkNvbnZlcnRpbmcgaW50byBhIGRvY3VtZW50IHRlcm0gbWF0cml4DQpgYGB7cn0NCmR0bS5yZXAucHJlIDwtIERvY3VtZW50VGVybU1hdHJpeChkb2NzLnJlcC5wcmUpDQpkdG0ucmVwLnBvc3QgPC0gRG9jdW1lbnRUZXJtTWF0cml4KGRvY3MucmVwLnBvc3QpDQpkdG0uZGVtLnByZSA8LSBEb2N1bWVudFRlcm1NYXRyaXgoZG9jcy5kZW0ucHJlKQ0KZHRtLmRlbS5wb3N0IDwtIERvY3VtZW50VGVybU1hdHJpeChkb2NzLmRlbS5wb3N0KQ0KDQojRmluZCB0aGUgc3VtIG9mIHdvcmRzIGluIGVhY2ggRG9jdW1lbnQNCnJvd1RvdGFscy5yZXAucHJlIDwtIGFwcGx5KGR0bS5yZXAucHJlICwgMSwgc3VtKSANCnJvd1RvdGFscy5yZXAucG9zdCA8LSBhcHBseShkdG0ucmVwLnBvc3QgLCAxLCBzdW0pDQpyb3dUb3RhbHMuZGVtLnByZSA8LSBhcHBseShkdG0uZGVtLnByZSAsIDEsIHN1bSkNCnJvd1RvdGFscy5kZW0ucG9zdCA8LSBhcHBseShkdG0uZGVtLnBvc3QgLCAxLCBzdW0pDQoNCmR0bS5yZXAucHJlICA8LSBkdG0ucmVwLnByZVtyb3dUb3RhbHMucmVwLnByZT4gMCwgXQ0KZHRtLnJlcC5wb3N0ICA8LSBkdG0ucmVwLnBvc3Rbcm93VG90YWxzLnJlcC5wb3N0PiAwLCBdDQpkdG0uZGVtLnByZSAgPC0gZHRtLmRlbS5wcmVbcm93VG90YWxzLmRlbS5wcmU+IDAsIF0NCmR0bS5kZW0ucG9zdCAgPC0gZHRtLmRlbS5wb3N0W3Jvd1RvdGFscy5kZW0ucG9zdD4gMCwgXQ0KYGBgDQoNCiMjIExEQQ0KVXNlIExEQSB0byBmaW5kIHRoZSB0b3AgMTAgdGVybXMgaW4gZWFjaCB0b3BpY3MNCmBgYHtyfQ0KYnVybmluIDwtIDQwMDANCml0ZXIgPC0gMjAwMA0KdGhpbiA8LSA1MDANCnNlZWQgPC1saXN0KDIwMDMsNSw2MywxMDAwMDEsNzY1KQ0KbnN0YXJ0IDwtIDUNCmJlc3QgPC0gVFJVRQ0KDQojTnVtYmVyIG9mIHRvcGljcw0KayA8LSAxMA0KDQojUnVuIExEQSB1c2luZyBHaWJicyBzYW1wbGluZw0KbGRhT3V0LnJlcC5wcmUgPC1MREEoZHRtLnJlcC5wcmUsIGssIG1ldGhvZD0iR2liYnMiLCBjb250cm9sPWxpc3QobnN0YXJ0PW5zdGFydCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IHNlZWQsIGJlc3Q9YmVzdCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXJuaW4gPSBidXJuaW4sIGl0ZXIgPSBpdGVyLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGluPXRoaW4pKQ0KbGRhT3V0LnJlcC5wb3N0IDwtTERBKGR0bS5yZXAucG9zdCwgaywgbWV0aG9kPSJHaWJicyIsIGNvbnRyb2w9bGlzdChuc3RhcnQ9bnN0YXJ0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gc2VlZCwgYmVzdD1iZXN0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1cm5pbiA9IGJ1cm5pbiwgaXRlciA9IGl0ZXIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaW49dGhpbikpDQpsZGFPdXQuZGVtLnByZSA8LUxEQShkdG0uZGVtLnByZSwgaywgbWV0aG9kPSJHaWJicyIsIGNvbnRyb2w9bGlzdChuc3RhcnQ9bnN0YXJ0LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gc2VlZCwgYmVzdD1iZXN0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ1cm5pbiA9IGJ1cm5pbiwgaXRlciA9IGl0ZXIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaW49dGhpbikpDQpsZGFPdXQuZGVtLnBvc3QgPC1MREEoZHRtLmRlbS5wb3N0LCBrLCBtZXRob2Q9IkdpYmJzIiwgY29udHJvbD1saXN0KG5zdGFydD1uc3RhcnQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQgPSBzZWVkLCBiZXN0PWJlc3QsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVybmluID0gYnVybmluLCBpdGVyID0gaXRlciwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpbj10aGluKSkNCiN3cml0ZSBvdXQgcmVzdWx0cw0KI2RvY3MgdG8gdG9waWNzDQpsZGFPdXQudG9waWNzLnJlcC5wcmUgPC0gYXMubWF0cml4KHRvcGljcyhsZGFPdXQucmVwLnByZSkpDQpsZGFPdXQudG9waWNzLnJlcC5wb3N0IDwtIGFzLm1hdHJpeCh0b3BpY3MobGRhT3V0LnJlcC5wb3N0KSkNCmxkYU91dC50b3BpY3MuZGVtLnByZSA8LSBhcy5tYXRyaXgodG9waWNzKGxkYU91dC5kZW0ucHJlKSkNCmxkYU91dC50b3BpY3MuZGVtLnBvc3QgPC0gYXMubWF0cml4KHRvcGljcyhsZGFPdXQuZGVtLnBvc3QpKQ0KDQoNCiN0b3AgMTAgdGVybXMgaW4gZWFjaCB0b3BpYw0KbGRhT3V0LnRlcm1zLnJlcC5wcmUgPC0gYXMubWF0cml4KHRlcm1zKGxkYU91dC5yZXAucHJlLDEwKSkNCmxkYU91dC50ZXJtcy5yZXAucG9zdCA8LSBhcy5tYXRyaXgodGVybXMobGRhT3V0LnJlcC5wb3N0LDEwKSkNCmxkYU91dC50ZXJtcy5kZW0ucHJlIDwtIGFzLm1hdHJpeCh0ZXJtcyhsZGFPdXQuZGVtLnByZSwxMCkpDQpsZGFPdXQudGVybXMuZGVtLnBvc3QgPC0gYXMubWF0cml4KHRlcm1zKGxkYU91dC5kZW0ucG9zdCwxMCkpDQoNCndyaXRlLmNzdihsZGFPdXQudGVybXMucmVwLnByZSxmaWxlPXBhc3RlKCIuLi9vdXRwdXQvTERBR2liYnMiLGssIlRvcGljc1RvVGVybXNSZXBQcmUuY3N2IikpDQp3cml0ZS5jc3YobGRhT3V0LnRlcm1zLnJlcC5wb3N0LGZpbGU9cGFzdGUoIi4uL291dHB1dC9MREFHaWJicyIsaywiVG9waWNzVG9UZXJtc1JlcFBvc3QuY3N2IikpDQp3cml0ZS5jc3YobGRhT3V0LnRlcm1zLmRlbS5wcmUsZmlsZT1wYXN0ZSgiLi4vb3V0cHV0L0xEQUdpYmJzIixrLCJUb3BpY3NUb1Rlcm1zRGVtUHJlLmNzdiIpKQ0Kd3JpdGUuY3N2KGxkYU91dC50ZXJtcy5kZW0ucG9zdCxmaWxlPXBhc3RlKCIuLi9vdXRwdXQvTERBR2liYnMiLGssIlRvcGljc1RvVGVybXNEZW1Qb3N0LmNzdiIpKQ0KDQpsZGFPdXQudGVybXMucmVwLnByZQ0KbGRhT3V0LnRlcm1zLnJlcC5wb3N0DQpsZGFPdXQudGVybXMuZGVtLnByZQ0KbGRhT3V0LnRlcm1zLmRlbS5wb3N0DQpgYGANCg0KIyMgQSBDbG9zZXIgTG9vayBvbiBTcGVjaWZpYyBUb3BpY3MNCg0KU29tZSB0b3BpY3MgY29uc2lzdGVudGx5IHNob3cgdXAgaW4gYWxsIGZvdXIgc3Vic2V0cywgZm9yIGV4YW1wbGU6IEFtZXJpY2EsIG5hdGlvbiwgbGF3LCBmcmVlZG9tLCByaWdodC4gSG93ZXZlciwgc29tZSB0b3BpY3Mgb25seSBzaG93IHVwIGluIGNlcnRhaW4gcGFydHkgb3IgdGltZSBwZXJpb2QuIEluIHRoaXMgc2VjdGlvbiwgbGV0J3MgbG9vayBhdCB0d28gdG9waWNzOiB3YXIgYW5kIHdvcmxkLg0KXG5ld2xpbmUNCg0KVGhlIHRvcGljIHdhciBjb25zdGFudGx5IHNob3dzIHVwIGluIFJldWJsaWNhbiBzcGVlY2hlcywgbm8gbWF0dGVyIHRoZSB0aW1lIHBlcmlvZC4gQXQgZmlyc3QsIEkgd2FzIHRoaW5raW5nLCBiZWZvcmUgMjB0aCBjZW50dXJ5LCB0aGVyZSB3YXMgQ2l2aWwgV2FyLCBhbmQgYWZ0ZXIgaW4gdGhlIDIwdGggY2VudHVyeSwgdGhlcmUgd2VyZSBXV0kgYW5kIFdXSUksIHNvIGl0J3Mga2luZCBvZiBtYWtlIHNlbnNlIHRvIGhhdmUgd2FyIG9uIGEgY29uc3RhbnQgdG9waWMuIEhvd2V2ZXIsIEkgcmVhbGl6ZSB0aGF0IHRoZSBwcmVzaWRlbnQgZHVyaW5nIFdXSSB3YXMgV29vZHJvdyBXaWxzb24sIGFuZCB0aGUgcHJlc2lkZW50IGR1cmluZyBXV0lJIHdhcyBGcmFua2xpbiBSb29zZXZlbHQsIGluIHdoaWNoIGJvdGggb2YgdGhlbSBhcmUgRGVtb2NyYXRzLiAgT25seSBBYnJhaGFtIExpbmNvbG4sIHdobyB3YXMgYSBSZXB1YmxpY2FuLCB3YXMgdGhlIHByZXNpZGVudCBkdXJpbmcgQ2l2aWwgV2FyLg0KXG5ld2xpbmUNCg0KVGhpcyBmYWN0IGludHJpZ3VlZCBtZSwgc28gSSBsb29rZWQgaW50byB0aGVpciBzcGVlY2hlcy4gSW4gTGluY29sbidzIHNwZWVjaGVzLCBoZSBtZW50aW9uZWQgIndhciIgb3ZlciAxMCB0aW1lcywgd2hpbGUgaW4gUm9vc2V2ZWx0J3MgdGhpcmQgdGVybSBzcGVlY2ggaGUgZGlkbid0IG1lbnRpb24gIndhciIgYXQgYWxsLCBhbmQgb25seSBvbmNlIGluIGhpcyBmb3VydGggaW5hdWd1cmF0aW9uIHNwZWVjaC4gDQpcbmV3bGluZQ0KDQpBbm90aGVyIHRvcGljIHRoYXQgY29tZXMgdG8gbXkgYXR0ZW50aW9uIGlzICJ3b3JsZCIsIHdoaWNoIGlzIHJhcmVseSB1c2VkIGJlZm9yZSAxOTAwcyBhbmQgYmVjb21lcyB3aWRlbHkgdXNlZCBwb3N0IDE5MDBzLiANClxuZXdsaW5lDQoNClRodXMsIGJhc2VkIG9uIHR3byBvYnNlcnZhdGlvbnMsIEkgZGVjaWRlIHRvIGNvdW50IHRoZSBvY2N1cmFuY2Ugb2YgY2VydGFpbiB0b3BpY3MgdG8gdmVyaWZ5IG15IG9ic2VydmF0aW9ucy4NCmBgYHtyfQ0KZG9jcy5yZXAucHJlMSA8LSB0bV9tYXAoZG9jcy5yZXAucHJlLFBsYWluVGV4dERvY3VtZW50KQ0KZG9jcy5yZXAucG9zdDEgPC0gdG1fbWFwKGRvY3MucmVwLnBvc3QsUGxhaW5UZXh0RG9jdW1lbnQpDQpkb2NzLmRlbS5wcmUxIDwtIHRtX21hcChkb2NzLmRlbS5wcmUsUGxhaW5UZXh0RG9jdW1lbnQpDQpkb2NzLmRlbS5wb3N0MSA8LSB0bV9tYXAoZG9jcy5kZW0ucG9zdCxQbGFpblRleHREb2N1bWVudCkNCg0Kd3Jkcy5yZXAucHJlMSA8LSBzdHJzcGxpdChwYXN0ZSh1bmxpc3QoZG9jcy5yZXAucHJlMSksIGNvbGxhcHNlID0gIiAiKSwgJyAnKVtbMV1dDQp3cmRzLnJlcC5wb3N0MSA8LSBzdHJzcGxpdChwYXN0ZSh1bmxpc3QoZG9jcy5yZXAucG9zdDEpLCBjb2xsYXBzZSA9ICIgIiksICcgJylbWzFdXQ0Kd3Jkcy5kZW0ucHJlMSA8LSBzdHJzcGxpdChwYXN0ZSh1bmxpc3QoZG9jcy5kZW0ucHJlMSksIGNvbGxhcHNlID0gIiAiKSwgJyAnKVtbMV1dDQp3cmRzLmRlbS5wb3N0MSA8LSBzdHJzcGxpdChwYXN0ZSh1bmxpc3QoZG9jcy5kZW0ucG9zdDEpLCBjb2xsYXBzZSA9ICIgIiksICcgJylbWzFdXQ0KDQp0YmxXcmRzLnJlcC5wcmUxIDwtIHRhYmxlKHdyZHMucmVwLnByZTEpDQp0YmxXcmRzLnJlcC5wb3N0MSA8LSB0YWJsZSh3cmRzLnJlcC5wb3N0MSkNCnRibFdyZHMuZGVtLnByZTEgPC0gdGFibGUod3Jkcy5kZW0ucHJlMSkNCnRibFdyZHMuZGVtLnBvc3QxIDwtIHRhYmxlKHdyZHMuZGVtLnBvc3QxKQ0KYGBgDQoNClRoZSBHZXRPY2N1cmVuY2UgbWV0aG9kIGlzIGJhc2VkIG9uIGEgc3RhY2tvdmVyZmxvdyBwb3N0DQpcbmV3bGluZQ0KDQpodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8zNTg4NzczMC9jb3VudGluZy1vY2N1cmVuY2Utb2YtYS13b3JkLWluLWEtdGV4dC1maWxlLXVzaW5nLXINCmBgYHtyfQ0KIyBHZXRPY2N1cmVuY2UgPC0gZnVuY3Rpb24od29yZCwgdGFibGUpIHsNCiMgICAgIG9jY3VyZW5jZSA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKQ0KIyAgICAgd29yZCA8LSBwYXN0ZTAoIlxcYiIsIHdvcmQpDQojICAgICBvY2N1cmVuY2UgPC0gb2NjdXJlbmNlW2dyZXAod29yZCwgb2NjdXJlbmNlWywxXSksIF0NCiMgICAgIHJldHVybihvY2N1cmVuY2UpDQojIH0NCg0KQ29tcGFyZU9jY3VyZW5jZSA8LSBmdW5jdGlvbih3b3JkKXsNCnRlc3QxIDwtIEdldE9jY3VyZW5jZSh3b3JkLCB0YmxXcmRzLnJlcC5wcmUxKQ0KdGVzdDIgPC0gR2V0T2NjdXJlbmNlKHdvcmQsIHRibFdyZHMucmVwLnBvc3QxKQ0KdGVzdDMgPC0gR2V0T2NjdXJlbmNlKHdvcmQsIHRibFdyZHMuZGVtLnByZTEpDQp0ZXN0NCA8LSBHZXRPY2N1cmVuY2Uod29yZCwgdGJsV3Jkcy5kZW0ucG9zdDEpDQpkZjEgPC0gbWVyZ2UodGVzdDEsIHRlc3QyLCBieS54ID0gIndyZHMucmVwLnByZTEiLCBieS55ID0gIndyZHMucmVwLnBvc3QxIiwgYWxsID0gVFJVRSkNCmRmMiA8LSBtZXJnZSh0ZXN0MywgdGVzdDQsIGJ5LnggPSAid3Jkcy5kZW0ucHJlMSIsIGJ5LnkgPSAid3Jkcy5kZW0ucG9zdDEiLCBhbGwgPSBUUlVFKQ0KZGYgPC0gbWVyZ2UoZGYxLCBkZjIsIGJ5LnggPSAid3Jkcy5yZXAucHJlMSIsIGJ5LnkgPSAid3Jkcy5kZW0ucHJlMSIsIGFsbCA9IFRSVUUpDQpjb2xuYW1lcyhkZikgPC0gYygiV29yZHMiLCAiUmVwLnByZSIsICJSZXAucG9zdCIsICJEZW0ucHJlIiwgIkRlbS5wb3N0IikNCnJldHVybihkZikNCn0NCg0KDQp3YXIgPC0gQ29tcGFyZU9jY3VyZW5jZSgid2FyIikNCmdsb2IgPC0gQ29tcGFyZU9jY3VyZW5jZSgiZ2xvYiIpDQp3b3JsZCA8LSBDb21wYXJlT2NjdXJlbmNlKCJ3b3JsZCIpDQoNCndyaXRlLmNzdih3YXIsIGZpbGUgPSAiLi4vb3V0cHV0L3dhci5jc3YiKQ0Kd3JpdGUuY3N2KGdsb2IsIGZpbGUgPSAiLi4vb3V0cHV0L2dsb2IuY3N2IikNCndyaXRlLmNzdih3b3JsZCwgZmlsZSA9ICIuLi9vdXRwdXQvd29ybGQuY3N2IikNCg0Kd2FyDQpnbG9iDQp3b3JsZA0KYGBgDQpGaXJzdCBvZiBhbGwsIG9uIHRoZSB0b3BpYyB3YXIgKHdvcmRzIGluY2x1ZGU6IHdhciwgd2Fyc2Vlaywgd2FyZmFyZSwgd2FydGltZSksIFJlcHVibGljYW5zIG1ldGlvbmVkIHRoaXMgdG9waWMgc2lnbmlmaWNhbnQgbW9yZSBmcmVxdWVudGx5IHRoYW4gRGVtb2NyYXRzLCBlc3BlY2lhbGx5IHBvc3QgMTkwMHMuIFByZXNpZGVudHMgZnJvbSBSdXB1YmxpY2FuIHBhcnR5IGhhdmUgbWVudGlvbmVkIHdhciBmb3Igb3ZlciAxNTggdGltZXMsIGNvbXBhcmUgd2l0aCA3OCB0aW1lcyBmcm9tIHRoZSBEZW1vY3JhdCBwYXJ0eS4NClxuZXdsaW5lDQoNClNlY29uZCwgdGhlIHRvcGljIHdvcmxkIG9yIGdsb2JlIGlzIG1vcmUgZnJlcXVlbnRseSBjb3ZlcmVkIGFmdGVyIDE5MDBzIGZvciBib3RoIFJlcHVibGljYW4gYW5kIERlbWNyYXQgcGFydGllcy4gQmVmb3JlIDE5MDBzLCB0aGUgd29yZCAid29ybGQiIGlzIG9ubHkgdXNlZCBpbiB0b3RhbCBvZiAxMDEgdGltZXMsIHdoZXJlYXMgYWZ0ZXIgMTkwMHMsIHRoaXMgd29yZCBpcyB1c2VkIGFsbW9zdCA4MDAgdGltZXMgaW4gdG90YWwuIEkgdGhpbmsgdGhpcyByZXN1bHQgY29pbmNpZGVzIHdpdGggdGhlIHRpbWVsaW5lIG9mIGdsb2JhbGl6YXRpb24uIEdsb2JhbGl6YXRpb24gYmVnYW4gaW4gdGhlIDE4MjBzLCBidXQgZGlkbid0IGdhaW4gbW9tZW50dWVtIHVudGlsIHRoZSBsYXRlIDE5dGggY2VudHVyeSBhbmQgZWFybHkgMjB0aCBjZW50dXJ5LiBJdCBvbmx5IGJlY29tZXMgcG9wdWxhciBpbiAxOTcwcy4NCg0KIyBDb25jbHVzaW9uDQpQcmVzaWRlbnRpYWwgc3BlZWNoZXMgZnJvbSBib3RoIHBhcnRpZXMgYW5kIGRpZmZlcmVudCB0aW1lIHBlcmlvZHMgc2hhcmUgbG90cyBvZiBzaW1pbGFyaXRpZXMuIEZpcnN0LCBhbGwgb2YgdGhlbSBkZWxpdmVyIHBvc2l0aXZlIGVtb3Rpb25zLCBzdWNoIGFzIHRydXN0IGFuZCBhbnRpY2lwYXRpb25zLiBBbHNvLCBpbiB0b3BpYyBtb2RlbGluZywgQW1lcmljYSwgbmF0aW9uLCBsYXcsIGZyZWVkb20sIHJpZ2h0IGFyZSBzb21lIGNvbW1vbiB0b3BpY3MgZm9yIGFsbCBhZGRyZXNzZXMuIA0KXG5ld2xpbmUNCg0KSG93ZXZlciwgYXMgZWFjaCBwcmVzaWRlbnRpYWwgYWRkcmVzcyBpcyB1bnFpdWUsIEkgdW5jb3ZlciBzb21lIGRpZmZlcmVuY2VzIGluIHRoZWlyIHNwZWVjaGVzIGJhc2VkIG9uIHRpbWUgYW5kIHBhcnR5IGRpZmZlcmVuY2VzLiBGaXJzdCBvZiBhbGwsIHRoZSBzcGVlY2ggc3RydWN0dXJlIGNoYW5nZXMgdGhyb3VnaCB0aW1lLiBJbiB0aGUgcGFzdCwgc3BlZWNoZXMgYXJlIGNvbXBvc2VkIGJ5IGxvbmcgc2VudGVuY2VzLCB3aGlsZSBpbiBub3dhZGF5cyBpbiBhIG1peHR1cmUgb2Ygc2hvcnQgYW5kIGxvbmcuIFRoZSBzaG9ydCBzZW50ZW5jZXMgaGF2ZSBzdHJvbmcgdG9uZSBhbmQgY29uY2lzZSB3aGljaCBpcyB2ZXJ5IHNsb2dhbi1saWtlLiBJbiBhZGRpdGlvbiwgZnJvbSB0b3BpYyBtb2RlbGluZyxJIGZpbmQgdGhhdCB0aGUgdG9waWMgb2YgIndvcmxkIiBhbmQgImdsb2JhbCIgZGlkbid0IGNvbWUgdXAgdW50aWwgMjB0aCBjZW50dXJ5LCB3aGljaCBjb25zdGFudCB0aGUgdGltZWxpbmUgb2YgZ2xvYmFsaXphdGlvbi4gUGFydHkgd2lzZSwgSSBvYnNlcnZlIHRoYXQgdGhlIHRvcGljICJ3YXIiIGlzIGZyZXF1ZW50bHkgbWVudGlvbmVkIGJ5IFJlYnVsaWNhbiBwcmVzaWRlbnRzLCBidXQgbm90IGEgbG90IGJ5IERlbW9jcmF0aWMgUHJlc2lkZW50cywgd2hpY2ggaXMgYSBnb29kIHJlZmxlY3Rpb24gb2YgZGlmZmVyZWNlcyBiZXR3ZWVuIHBhcnRpZXMnIGZ1bmRlbWVudGFsIHBvbGl0aWNhbCB2aWV3cy4=